В Python 2.7: я измеряю процесс, который считает ключи словаря, возвращенного функцией.

Показан базовый пример, где функция getList () возвращает список символов, которые могут быть ['a'], ['b'], ['c'] или ['d']; большинство списков являются отдельными элементами, хотя иногда могут быть возвращены два, например, ['a', 'd']. Я хотел бы посчитать все вернулось. Способ, которым я думал об этом, показан ниже:

    myDict = {'a':0, 'b':0, 'c':0, 'd':0, 'error':0, 'total':0}
    for key in charList:
        myDict[key] += 1
        myDict['total'] += 1

Есть ли более Pythonic способ, возможно, словарь для подсчета ключей в списках (различной длины)?

import random

def getList():
    '''mimics a prcoess that returns a list of chars between a - d
       [most lists are single elements, though some are two elements]'''
    number = (random.randint(97,101))
    if number == 101:
        charList = [chr(number-1), chr(random.randint(97,100))]
        if charList[0] == charList[1]:
            getList()            
    else:
        charList = [chr(number)]
    return charList


myDict = {'a':0, 'b':0, 'c':0, 'd':0, 'error':0, 'total':0}

for counter in range(0,5):
    charList = getList()
    for key in charList:
        print charList, '\t', key
        try:
            myDict[key] += 1
            myDict['total'] += 1
        except:
            myDict['error'] += 1

print "\n",myDict

Сгенерированный результат:

Output

1
Harry Lime 15 Дек 2015 в 15:08

4 ответа

Лучший ответ

Вы можете использовать встроенный класс collections.Counter: https: / /docs.python.org/2/library/collections.html#collections.Counter

Например, с вашим кодом:

import collections
ctr = collections.Counter()

for ii in range(0,5):
    charList = getList()
    ctr.update(charList)

ctr['total'] = sum(ctr.values())
print ctr

Это напечатает:

Counter({'total': 7, 'd': 5, 'a': 1, 'c': 1})
1
John Zwinck 15 Дек 2015 в 12:12

Самый простой способ, который я могу придумать, это сгладить ваш список с помощью chain, а затем использовать Counter: пусть lst будет списком [['a'], ['b '], [' c '], [' d '], [' a ',' d ']]

>>> from itertools import chain
>>> from collections import Counter
>>> c = Counter(chain(*lst))
>>> c['total'] = sum(c.values())
>>> c
Counter({'total': 6, 'd': 2, 'a': 2, 'b': 1, 'c': 1})
0
timgeb 15 Дек 2015 в 12:21

Используйте collections.Counter и выражение генератора двойной петли для подачи отдельных элементов в счетчик:

>>> lst = [['a'], ['a', 'b'], ['c'], ['c', 'd']]
>>> c = collections.Counter((y for x in lst for y in x))
>>> c
Counter({'a': 2, 'c': 2, 'b': 1, 'd': 1})
>>> c.most_common(2)
[('a', 2), ('c', 2)]
>>> sum(c.values())
6
0
tobias_k 15 Дек 2015 в 12:14

Вы можете использовать collections.Counter:

# You need to initialize the counter or you won't get the entry with 0 count.
myDict = collections.Counter({'a': 0, 'b': 0, 'c': 0, 'd': 0})
myDict.update(x for _ in range(0, 5) for x in getList())
# Then create the 'total' entry
myDict['total'] = sum(myDict.values())

Примечание. Это может добавить новые ключи к счетчику без установки записи 'error', если list, возвращаемый getList(), содержит новые символы ('e', {{X4} }, ...).

1
Holt 15 Дек 2015 в 12:26