2016-11-09 5 views
2

Я просто столкнулся с проблемой, что мне нужно поставить список, например. l = [1, 2, 3, 4], в дик, например. {1: 1, 2: 1, 3: 1, 4: 1}. Я просто хочу знать, следует ли мне использовать collection.Counter() или просто написать цикл самостоятельно, чтобы сделать это. Является ли встроенный метод быстрее, чем писать цикл самостоятельно?Python collections.Counter() runtime

+2

Используйте 'collections.Counter()' потому что это то, что он делает. Зачем писать свой собственный код;) –

+0

Вы всегда можете * проверить *, если что-то быстрее, с модулем 'timeit'. В Python 3 объект «Counter» имеет улучшенные характеристики C и очень быстро работает. –

+0

@MartijnPieters: Я вычислил его с помощью 'timeit', а мой собственный код быстрее, чем' Counter'. Может быть, я сделал что-то не так, но все выглядит так же, как и у меня. –

ответ

3

Вы всегда можете указать тест, если что-то быстрее, с модулем timeit. В Python 3, Counter объект имеет повышение производительности C и очень быстро на самом деле:

>>> from timeit import timeit 
>>> import random, string 
>>> from collections import Counter, defaultdict 
>>> def count_manually(it): 
...  res = defaultdict(int) 
...  for el in it: 
...   res[el] += 1 
...  return res 
... 
>>> test_data = [random.choice(string.printable) for _ in range(10000)] 
>>> timeit('count_manually(test_data)', 'from __main__ import test_data, count_manually', number=2000) 
1.4321454349992564 

>>> timeit('Counter(test_data)', 'from __main__ import test_data, Counter', number=2000) 
0.776072466003825 

Здесь Counter() был в 2 раза быстрее.

При этом, если вы не рассчитываете на критическую для вас критическую часть кода, сосредоточьтесь на удобочитаемости и ремонтопригодности, и в этом отношении Counter() выигрывает раздачу с помощью собственного кода.

Рядом все, что Counter() объектов предлагают функциональность поверх словарей: их можно рассматривать как мультимножества (можно суммировать или вычитать счетчики, и производит объединение или пересечение), и они могут эффективно дать вам Top N элементов по счету.

+0

Да, вы правы. В Python 2 он медленнее, но быстрее в Python 3 –

+0

Спасибо большое! –

1

Это зависит от читаемость v/s эффективность. Давайте сначала рассмотрим обе реализации. Я буду использовать это в качестве списка для образца запуска:

my_list = [1, 2, 3, 4, 4, 5, 4, 3, 2] 

Использования collections.Counter():

from collections import Counter 
d = Counter(my_list) 

Использование collections.defaultdict() создания моего собственного счетчика:

from collections import defaultdict 
d = defaultdict(int) 
for i in [1, 2, 3, 4, 4, 5, 4, 3, 2]: 
    d[i] += 1 

Как вы видите, collections.Counter() является более читаемый

Посмотрим эффективность использования timeit:

  • В Python 2.7:

    mquadri$ python -m "timeit" -c "from collections import defaultdict" "d=defaultdict(int)" "for i in [1, 2, 3, 4, 4, 5, 4, 3, 2]: d[i] += 1" 
    100000 loops, best of 3: 2.95 usec per loop 
    
    mquadri$ python -m "timeit" -c "from collections import Counter" "Counter([1, 2, 3, 4, 4, 5, 4, 3, 2])" 
    100000 loops, best of 3: 6.5 usec per loop 
    

    collection.Counter() реализация медленнее в 2 раза, чем собственный код.

  • В Python 3:

    mquadri$ python3 -m "timeit" -c "from collections import defaultdict" "d=defaultdict(int)" "for i in [1, 2, 3, 4, 4, 5, 4, 3, 2]: d[i] += 1" 
    100000 loops, best of 3: 3.1 usec per loop 
    
    mquadri$ python3 -m "timeit" -c "from collections import Counter" "Counter([1, 2, 3, 4, 4, 5, 4, 3, 2])" 
    100000 loops, best of 3: 5.57 usec per loop 
    

    collections.Counter() в два раза быстрее, так как собственный код.

+0

Спасибо! Очень ясно! –

Смежные вопросы