collections.Counter
在Python中提供的most_common
函数的复杂度是怎样的?
更具体地说,当计数时,Counter
是否会保持某种排序列表,使得它可以在n
为添加到计数器中的(唯一)项目数量时,比O(n)
更快地执行most_common
操作?为了您的信息,我正在处理大量文本数据,试图找到第n个最常见的令牌。
我查看了官方文档和CPython维基上的Time Complexity文章,但我没有找到答案。
collections.Counter
在Python中提供的most_common
函数的复杂度是怎样的?
更具体地说,当计数时,Counter
是否会保持某种排序列表,使得它可以在n
为添加到计数器中的(唯一)项目数量时,比O(n)
更快地执行most_common
操作?为了您的信息,我正在处理大量文本数据,试图找到第n个最常见的令牌。
我查看了官方文档和CPython维基上的Time Complexity文章,但我没有找到答案。
heapq.nlargest
。这是一个 O(k) + O((n - k) log k) + O(k log k) 的算法,对于小的常量 k
来说非常好,因为它基本上是线性的。O(k) 部分来自对初始的 k 个计数进行堆化,第二部分来自 n-k 次对 heappushpop 方法的调用,第三部分来自对 k 个元素的最终堆进行排序。由于 k <= n,所以可以得出复杂度:
如果 `k = 1`,那么很容易证明复杂度为:O(n log k)
O(n)
源码 明确展示了发生的情况:
def most_common(self, n=None):
'''List the n most common elements and their counts from the most
common to the least. If n is None, then list all element counts.
>>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 2)]
'''
# Emulate Bag.sortedByCount from Smalltalk
if n is None:
return sorted(self.iteritems(), key=_itemgetter(1), reverse=True)
return _heapq.nlargest(n, self.iteritems(), key=_itemgetter(1))
heapq.nlargest
定义在 heapq.py 中。
n log n
,或者使用heapq.nlargest,它是O(n * log(k))
。 - Padraic Cunningham