An example found in the French forum: http://www.developpez.net/forums/d962510/autres-langages/python-zope/general-python/operations-listes-dictionnaires/.
A guy wanted to transform a dictionary like this:
d= {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
into the list of occurence of each id:
[('r', [1, 3]), ('t', [4, 4, 6])]
One of the answers was:
L=[(d['id'][i],d['Ei'][i]) for i in xrange(0,len(d['Ei']))] R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
Quite efficient!
The first step is to build a dictionary with the correspondances between the id and the Ei, the L:
[('r', 1), ('r', 3), ('t', 4), ('t', 4), ('t', 6)]
This is done with something like this:
This is done with something like this:
In [8]: L2 = []
In [9]: for i in xrange(0,len(d['Ei'])):
...: L2.append((d['id'][i],d['Ei'][i]))
Which can effectively be compacted as:
...: L2.append((d['id'][i],d['Ei'][i]))
Which can effectively be compacted as:
L=[(d['id'][i],d['Ei'][i]) for i in xrange(0,len(d['Ei']))]
The second step (R) is the list comprehension form of the following, where we are counting the occurences of each id. First find the set of the different and uniq values of id: set() gives the solution.
Then looping on these values and find the occurences for each values. Finally put all this into a dictionary. The expand form would be:
R2=[]
uniqid = set(d['id'])
for x in uniqid:
for y in L:
if y[0]==x:
R2.append([x,[y[1]]])
for x in uniqid:
for y in L:
if y[0]==x:
R2.append([x,[y[1]]])
What can also be obtained like this:
R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
This is more compact, in some sense more elegant, and I think more efficient (quicker), but not really sure of that...