Коллекции Python.Counter: most_common complex
Какова сложность функции most_common
предоставляемой объектом collections.Counter
в Python?
Более конкретно, хранит ли Counter
какой-то отсортированный список во время подсчета, позволяя ему выполнять операцию most_common
быстрее, чем O(n)
когда n
- это количество (уникальных) элементов, добавленных к счетчику? Для вашей информации, я обрабатываю большое количество текстовых данных, пытаясь найти n-й самый частый токен.
Я проверил официальную документацию и статью TimeComplexity в вики CPython, но не смог найти ответ.
Ответы
Ответ 1
Из исходного кода collection.py мы видим, что если мы не указываем количество возвращаемых элементов, most_common
возвращает отсортированный список подсчетов. Это алгоритм O(n log n)
.
Если мы используем most_common
для возврата k > 1
элементов, то мы используем heapq.nlargest
. Это алгоритм O(k) + O((n - k) log k) + O(k log k)
, который очень хорош для небольшой константы k
, поскольку он существенно линейный. Часть O(k)
получается из кучи начальных значений k
, вторая часть из n - k
вызывает метод heappushpop
а третья часть - из сортировки конечной кучи из k
элементов. Поскольку k <= n
мы можем заключить, что сложность составляет:
O (n log k)
Если k = 1
то легко показать, что сложность равна:
На)
Ответ 2
Источник показывает, что именно происходит:
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