who said that ignorance is a bliss didn’t try python :) This is the assignment : you have a list of dictionaries with a field date and you want to group all these dictionaries in a map date -> list of dictionaries with this date.
The first solution that came to my mind was something ugly like :
def group_by_date(qs):
by_date = {}
for r in qs :
l = by_date.get(r['date'],[])
l.append(r)
by_date[r['date']] = l
return by_date
for example :
In [36]: group_by_date([{'date' : 1},{'date' : 2}])
Out[36]: {1: [{'date': 1}], 2: [{'date': 2}]}
6 lines of python !!! unacceptable. It hurt my eyes and it is not easy to read. The good people on the #python irc channel adviced me to check the collections.defaultdict and this is actually pretty neat. Now I can write something like
from collections import defaultdict
def group_by_date(qs):
by_date = defaultdict(list)
for r in qs :
by_date[r['date']].append(r)
return by_date
In [47]: group_by_date([{'date' : 1},{'date' : 2}])
Out[47]: defaultdict(<type 'list'>, {1: [{'date': 1}], 2: [{'date': 2}]})
Nice, but still … and we can do better ! itertools.groupby on the rescue :
from itertools import groupby
qs = [{'date' : 1},{'date' : 2}]
[(name, list(group)) for name, group in itertools.groupby(qs, lambda p:p['date'])]
Out[77]: [(1, [{'date': 1}]), (2, [{'date': 2}])]
Ah ! Nirvana :) I’ve to admit the most readable solution is using defaultdict, but this solution using groupby is a wonderful power-tool. If you understand list comprehension, this is a very natural solution to the problem.