Коллекции 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