在Python中,如何在不保留大量值的情况下获得不同值的计数

在Python中,如何在不保留大量值的情况下获得不同值的计数,python,data-structures,Python,Data Structures,我想计算不同值的数量,我最简单的解决方案是保留一个集合并更新它,直到我完成迭代,然后我得到这个集合的len作为我的答案 但是,当数据集很大时,这是不可能的。我不仅要为每次迭代计算一种不同的值,这意味着我必须保留更多的集合 我想知道有没有更好的办法?也许其他一些内置数据结构可以帮助我?谢谢 使用。有几个python库,例如。或者查看此堆栈溢出答案以创建自己的堆栈溢出。每次向Trie中添加新词时递增计数器 下面是一个简单的嵌套字典实现。它记录单词总数和每个单词的数量 END = 'end' cla

我想计算不同值的数量,我最简单的解决方案是保留一个
集合
并更新它,直到我完成迭代,然后我得到这个集合的
len
作为我的答案

但是,当数据集很大时,这是不可能的。我不仅要为每次迭代计算一种不同的值,这意味着我必须保留更多的集合

我想知道有没有更好的办法?也许其他一些内置数据结构可以帮助我?谢谢

使用。有几个python库,例如。或者查看此堆栈溢出答案以创建自己的堆栈溢出。每次向Trie中添加新词时递增计数器

下面是一个简单的嵌套字典实现。它记录单词总数和每个单词的数量

END = 'end'

class Trie:

    def __init__(self, words_iterable):
        self.root = {}
        self.size = 0

        for word in iter(words_iterable):
            self.insert(word)

    def insert(self, word):
        current_dict = self.root
        for letter in word:
            current_dict = current_dict.setdefault(letter, {})

        if END not in current_dict:
            current_dict[END] = 0
            self.size += 1
        current_dict[END] += 1

    def count(self, word):
        current_dict = self.root
        for letter in word:
            current_dict = current_dict.setdefault(letter, {})
        return current_dict.get(END, 0)

    def __len__(self):
        return self.size

    def __str__(self):
        return str(self.root)
示例:

trie = Trie('one two one three four'.split())
trie.insert('four')

print(trie)

>>> {'o': {'n': {'e': {'end': 2}}}, 't': {'w': {'o': {'end': 1}}, 'h': {'r':
    {'e': {'e': {'end': 1}}}}}, 'f': {'o': {'u': {'r': {'end': 2}}}}}

len(trie)
>>> 4

trie.count('four')
>>> 2
使用一个。有几个python库,例如。或者查看此堆栈溢出答案以创建自己的堆栈溢出。每次向Trie中添加新词时递增计数器

下面是一个简单的嵌套字典实现。它记录单词总数和每个单词的数量

END = 'end'

class Trie:

    def __init__(self, words_iterable):
        self.root = {}
        self.size = 0

        for word in iter(words_iterable):
            self.insert(word)

    def insert(self, word):
        current_dict = self.root
        for letter in word:
            current_dict = current_dict.setdefault(letter, {})

        if END not in current_dict:
            current_dict[END] = 0
            self.size += 1
        current_dict[END] += 1

    def count(self, word):
        current_dict = self.root
        for letter in word:
            current_dict = current_dict.setdefault(letter, {})
        return current_dict.get(END, 0)

    def __len__(self):
        return self.size

    def __str__(self):
        return str(self.root)
示例:

trie = Trie('one two one three four'.split())
trie.insert('four')

print(trie)

>>> {'o': {'n': {'e': {'end': 2}}}, 't': {'w': {'o': {'end': 1}}, 'h': {'r':
    {'e': {'e': {'end': 1}}}}}, 'f': {'o': {'u': {'r': {'end': 2}}}}}

len(trie)
>>> 4

trie.count('four')
>>> 2

如果您对O(NlogN)时间(即首先对列表进行排序)没有问题,可以使用恒定内存执行此操作。@cs95 timsort是O(n)空间复杂度,因此它不能完全解决此问题。我们需要利用这个世界Quicksort@OlivierMelançon aaah。。。公平地说,一些快速研究表明timsort使用的内存可能高达N//2(这仍然是线性的,对OP来说是一个挑战)。@cs95抱歉,我不太理解你的解决方案。我的情况是:我必须迭代一个文档集来计算当前文档中单词的一些属性。这些属性包括distinct value count(例如,引用当前文档的distinct document的数量),因此我为这些属性维护一个
,并最终计算该集的长度。我怎样才能把你的解决方案应用到这个问题上?谢谢只要你的设备能存储在内存中,这可能是你最好的解决方案。大多数专门的解决方案通常处理这个数据集大于内存的问题。如果您对O(NlogN)时间(即首先对列表进行排序)没有问题,那么您可以使用恒定内存来完成这项工作。@cs95 timsort是O(n)空间复杂度,因此它不能完全解决这个问题。我们需要利用这个世界Quicksort@OlivierMelançon aaah。。。公平地说,一些快速研究表明timsort使用的内存可能高达N//2(这仍然是线性的,对OP来说是一个挑战)。@cs95抱歉,我不太理解你的解决方案。我的情况是:我必须迭代一个文档集来计算当前文档中单词的一些属性。这些属性包括distinct value count(例如,引用当前文档的distinct document的数量),因此我为这些属性维护一个
,并最终计算该集的长度。我怎样才能把你的解决方案应用到这个问题上?谢谢只要你的设备能存储在内存中,这可能是你最好的解决方案。大多数专门的解决方案通常处理数据集大于内存的问题。由于额外的dict和字节码解释的所有开销,这很可能比直接的集合解决方案要昂贵得多。字典字典字典如何比单个集合更好?这似乎解决了不同的问题。这绝对值得一试,但取决于OP数据集。这会带来很大的开销,但由于单词之间的冲突,随着时间的推移,大小可能会越来越慢。我同意简单的python嵌套字典实现可能并不理想。如果OP需要更好的空间/时间效率,那么玛丽莎TIE链接就要实现Cython,并且有一个具有Python绑定的C++实现。在Marisa trie链接上,它表示可以比普通字典(set)节省50-100倍的空间。但它取决于数据集。@RadosławCybulski就像一个集合一样,Trie只存储每个字符串的一个副本。它可以在一个集合上节省空间,因为字符串的每个前缀只存储一次。在本例中,“two”和“three”中的“t”只存储一次。由于额外的dict和字节码解释的所有开销,这很可能比直接的集合解决方案要昂贵得多。字典字典字典如何比单个集合更好?这似乎解决了不同的问题。这绝对值得一试,但取决于OP数据集。这会带来很大的开销,但由于单词之间的冲突,随着时间的推移,大小可能会越来越慢。我同意简单的python嵌套字典实现可能并不理想。如果OP需要更好的空间/时间效率,那么玛丽莎TIE链接就要实现Cython,并且有一个具有Python绑定的C++实现。在Marisa trie链接上,它表示可以比普通字典(set)节省50-100倍的空间。但它取决于数据集。@RadosławCybulski就像一个集合一样,Trie只存储每个字符串的一个副本。它可以在一个集合上节省空间,因为字符串的每个前缀只存储一次。在本例中,“two”和“three”中的“t”只存储一次。