MFB
MFB

Reputation: 19787

What is a Pythonic way to count dictionary values in list of dictionaries

For a list like this:

for i in range(100):
    things.append({'count':1})

for i in range(100):
    things.append({'count':2})

To count the number of 1 in list:

len([i['count'] for i in things if i['count'] == 1])

What is a better way?

Upvotes: 1

Views: 190

Answers (1)

Alex L
Alex L

Reputation: 8925

collections.Counter

>>> from collections import Counter
>>> c = Counter([thing['count'] for thing in things])
>>> c[1]               # Number of elements with count==1
100
>>> c[2]               # Number of elements with count==2
100
>>> c.most_common()    # Most common elements
[(1, 100), (2, 100)]
>>> sum(c.values())    # Number of elements
200
>>> list(c)            # List of unique counts
[1, 2]
>>> dict(c)            # Converted to a dict 
{1: 100, 2: 100}

Perhaps you could do something like this?

class DictCounter(object):
    def __init__(self, list_of_ds):
        for k,v in list_of_ds[0].items():
            self.__dict__[k] = collections.Counter([d[k] for d in list_of_ds])

>>> new_things = [{'test': 1, 'count': 1} for i in range(10)]
>>> for i in new_things[0:5]: i['count']=2

>>> d = DictCounter(new_things)
>>> d.count
Counter({1: 5, 2: 5})
>>> d.test
Counter({1: 10})

Extended DictCounter to handle missing keys:

>>> class DictCounter(object):
    def __init__(self, list_of_ds):
        keys = set(itertools.chain(*(i.keys() for i in list_of_ds)))
        for k in keys:
            self.__dict__[k] = collections.Counter([d.get(k) for d in list_of_ds])

>>> a = [{'test': 5, 'count': 4}, {'test': 3, 'other': 5}, {'test':3}, {'test':5}]
>>> d = DictCounter(a)
>>> d.test
Counter({3: 2, 5: 2})
>>> d.count
Counter({None: 3, 4: 1})
>>> d.other
Counter({None: 3, 5: 1})

Upvotes: 3

Related Questions