My problem is simple: I have a list of dicts, and I want to make a count aggregation of this into a new dictionary, on a particular key. Just like this, but in Python.
mylist = [
{'date': '16-01-2016', 'name': 'A'},
{'date': '16-01-2016', 'name': 'B'},
{'date': '17-01-2016', 'name': 'C'},
{'date': '17-01-2016', 'name': 'D'},
{'date': '17-01-2016', 'name': 'E'},
{'date': '18-01-2016', 'name': 'F'},
]
{'17-01-2016': 3, '16-01-2016': 2, '18-01-2016': 1}
What is the best solution to achieve this? I would like to do it a more beautiful and pythonic way than that ugly piece of code:
result = {}
for item in mylist:
if not item['date'] in result:
result[item['date']] = 1
else:
result[item['date']] += 1
Many thanks for considering my request!
You can use a collections.Counter dict with map and operator.itemgetter:
from collections import Counter
from operator import itemgetter
mylist = [
{'date': '16-01-2016', 'name': 'A'},
{'date': '16-01-2016', 'name': 'B'},
{'date': '17-01-2016', 'name': 'C'},
{'date': '17-01-2016', 'name': 'D'},
{'date': '17-01-2016', 'name': 'E'},
{'date': '18-01-2016', 'name': 'F'},
]
counts = Counter(map(itemgetter("date"), mylist))
Output:
Counter({'17-01-2016': 3, '16-01-2016': 2, '18-01-2016': 1})
Or using just a gen exp:
counts = Counter(d["date"] for d in mylist)
If you are using python2, use itertools.imap in place of map.
On a side note, if item['date'] not in result
reads better than if not item['date'] in result
.
If speed really matters, the map and itemgetter will be a little faster:
In [16]: timeit Counter(map(itemgetter("date"), mylist))
10 loops, best of 3: 23.9 ms per loop
In [17]: timeit Counter(d["date"] for d in mylist)
10 loops, best of 3: 26.8 ms per loop
In [18]: timeit Counter(map(lambda x: x['date'], mylist))
10 loops, best of 3: 34.9 ms per loop
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments