эффективный способ подсчета элемента в словаре в Python с использованием цикла

У меня есть список значений. Я хочу подсчитать во время цикла число элементов для каждого класса (т. Е. 1,2,3,4,5)

mylist = [1,1,1,1,1,1,2,3,2,2,2,2,3,3,4,5,5,5,5] mydict = dict() for index in mylist: mydict[index] = +1 mydict Out[344]: {1: 1, 2: 1, 3: 1, 4: 1, 5: 1} 

Я хочу получить этот результат

 Out[344]: {1: 6, 2: 5, 3: 3, 4: 1, 5: 4} 

5 Solutions collect form web for “эффективный способ подсчета элемента в словаре в Python с использованием цикла”

Для вашего меньшего примера, с ограниченным разнообразием элементов, вы можете использовать набор и понимание dict:

 >>> mylist = [1,1,1,1,1,1,2,3,2,2,2,2,3,3,4,5,5,5,5] >>> {k:mylist.count(k) for k in set(mylist)} {1: 6, 2: 5, 3: 3, 4: 1, 5: 4} 

Чтобы разбить его, set(mylist) удалить список и сделать его более компактным:

 >>> set(mylist) set([1, 2, 3, 4, 5]) 

Затем понимание словаря проходит через уникальные значения и задает счет из списка.

Это также значительно быстрее, чем использование счетчика и быстрее, чем использование setdefault:

 from __future__ import print_function from collections import Counter from collections import defaultdict import random mylist=[1,1,1,1,1,1,2,3,2,2,2,2,3,3,4,5,5,5,5]*10 def s1(mylist): return {k:mylist.count(k) for k in set(mylist)} def s2(mlist): return Counter(mylist) def s3(mylist): mydict=dict() for index in mylist: mydict[index] = mydict.setdefault(index, 0) + 1 return mydict def s4(mylist): mydict={}.fromkeys(mylist,0) for k in mydict: mydict[k]=mylist.count(k) return mydict def s5(mylist): mydict={} for k in mylist: mydict[k]=mydict.get(k,0)+1 return mydict def s6(mylist): mydict=defaultdict(int) for i in mylist: mydict[i] += 1 return mydict def s7(mylist): mydict={}.fromkeys(mylist,0) for e in mylist: mydict[e]+=1 return mydict if __name__ == '__main__': import timeit n=1000000 print(timeit.timeit("s1(mylist)", setup="from __main__ import s1, mylist",number=n)) print(timeit.timeit("s2(mylist)", setup="from __main__ import s2, mylist, Counter",number=n)) print(timeit.timeit("s3(mylist)", setup="from __main__ import s3, mylist",number=n)) print(timeit.timeit("s4(mylist)", setup="from __main__ import s4, mylist",number=n)) print(timeit.timeit("s5(mylist)", setup="from __main__ import s5, mylist",number=n)) print(timeit.timeit("s6(mylist)", setup="from __main__ import s6, mylist, defaultdict",number=n)) print(timeit.timeit("s7(mylist)", setup="from __main__ import s7, mylist",number=n)) 

На моей машине, которая печатает (Python 3):

 18.123854104997008 # set and dict comprehension 78.54796334600542 # Counter 33.98185228800867 # setdefault 19.0563529439969 # fromkeys / count 34.54294775899325 # dict.get 21.134678319009254 # defaultdict 22.760544238000875 # fromkeys / loop 

Для более крупных списков, таких как 10 миллионов целых чисел, с более разнообразными элементами (1500 случайных чисел), используйте defaultdict или fromkeys в цикле:

 from __future__ import print_function from collections import Counter from collections import defaultdict import random mylist = [random.randint(0,1500) for _ in range(10000000)] def s1(mylist): return {k:mylist.count(k) for k in set(mylist)} def s2(mlist): return Counter(mylist) def s3(mylist): mydict=dict() for index in mylist: mydict[index] = mydict.setdefault(index, 0) + 1 return mydict def s4(mylist): mydict={}.fromkeys(mylist,0) for k in mydict: mydict[k]=mylist.count(k) return mydict def s5(mylist): mydict={} for k in mylist: mydict[k]=mydict.get(k,0)+1 return mydict def s6(mylist): mydict=defaultdict(int) for i in mylist: mydict[i] += 1 return mydict def s7(mylist): mydict={}.fromkeys(mylist,0) for e in mylist: mydict[e]+=1 return mydict if __name__ == '__main__': import timeit n=1 print(timeit.timeit("s1(mylist)", setup="from __main__ import s1, mylist",number=n)) print(timeit.timeit("s2(mylist)", setup="from __main__ import s2, mylist, Counter",number=n)) print(timeit.timeit("s3(mylist)", setup="from __main__ import s3, mylist",number=n)) print(timeit.timeit("s4(mylist)", setup="from __main__ import s4, mylist",number=n)) print(timeit.timeit("s5(mylist)", setup="from __main__ import s5, mylist",number=n)) print(timeit.timeit("s6(mylist)", setup="from __main__ import s6, mylist, defaultdict",number=n)) print(timeit.timeit("s7(mylist)", setup="from __main__ import s7, mylist",number=n)) 

Печать:

 2825.2697427899984 # set and dict comprehension 42.607481333994656 # Counter 22.77713537499949 # setdefault 2853.11187016801 # fromkeys / count 23.241977066005347 # dict.get 15.023175164998975 # defaultdict 18.28165417900891 # fromkeys / loop 

Вы можете видеть, что решения, которые ретранслируют по count с умеренным количеством раз в большом списке, будут страдать / катастрофически по сравнению с другими решениями.

Попробуйте collections.Counter :

  >>> from collections import Counter >>> Counter([1,1,1,1,1,1,2,3,2,2,2,2,3,3,4,5,5,5,5]) Counter({1: 6, 2: 5, 5: 4, 3: 3, 4: 1}) 

В вашем коде вы можете в основном заменить mydict на Counter и write

 mydict[index] += 1 

вместо

 mydict[index] = +1 

setdefault подхода setdefault является setdefault collections.defaultdict . Это немного быстрее.

 def foo(mylist): d=defaultdict(int) for i in mylist: d[i] += 1 return d 

itertools.groupBy предоставляет другой вариант. Это скорость примерно такая же, как у Counter (по крайней мере, на 2,7)

 {x[0]:len(list(x[1])) for x in itertools.groupby(sorted(mylist))} 

Однако тесты времени в этом небольшом списке тестов могут быть не одинаковыми при работе с 32 ГБ данных, которые OP упоминает в комментарии.


Я выполнил несколько из этих опций в случае подсчета слов в верхнем слове n на вершине python, почему многопроцессор медленнее, чем один процесс

Там OP использовал Counter, и пытался ускорить работу, используя многопроцессорность. С текстовым файлом в defaultdict счетчик, использующий defaultdict был быстрым, занимает 0.2 сек. Сортировка вывода для получения 40 верхних слов занимает столько же, сколько и подсчет.

Counter был немного медленнее на 3.2 , и намного медленнее на 2.7 . Это потому, что 3.2 скомпилированная версия ( .so файл).

Но счетчик, использующий mylist.count в состоянии покоя при обработке большого списка; почти 200 сек. Он должен много раз искать этот большой список, один раз собирать ключи, а затем один раз для каждого ключа, когда он подсчитывает.

Чтобы исправить код:

 mydict[index] = +1 

должно быть:

 mydict[index] = mydict.setdefault(index, 0) + 1 

Ваш код присваивает значение 1 для каждого ключа. Замените mydict[index] = +1 с помощью mylist.count(index)

Это должно работать:

 mylist = [1,1,1,1,1,1,2,3,2,2,2,2,3,3,4,5,5,5,5] mydict = dict() for index in mylist: mydict[index] = mylist.count(index) mydict 
  • «Интерфейсы» в Python: да или нет?
  • Определить кодировку текста в Python
  • Должны ли операторы импорта Python всегда находиться в верхней части модуля?
  • Python "string_escape" против "unicode_escape"
  • Как получить кодировку терминала из сценария python?
  • Специальные символы Python в строках
  • Python - лучший язык программирования в мире.