Reputation: 105
I never used python before. Now I have a dictionary like :
d1 = {1:2,3:3,2:2,4:2,5:2}
The pair[0] in each pair means point, the pair[1] in each pair means the cluster id. So d1 means point 1 belongs to cluster 2, point 3 belongs to cluster 3, point 2 belongs to cluster 2, point 4 belongs to cluster 2, point 5 belongs to cluster 2. No point belongs to cluster 1. How to use filter(don't use loop) to get a dictionary like following :
d2 = {1:[],2:[1,2,4,5],3:[3]}
it means no point belongs to cluster 1, 1,2,4,5 belongs to cluster 2, 3 belongs to cluster 3. I tried :
d2 = dict(filter(lambda a,b: a,b if a[1] == b[1] , d1.items()))
Upvotes: 1
Views: 175
Reputation: 310237
I would use a collections.defaultdict
from collections import defaultdict
d2 = defaultdict(list)
for point, cluster in d1.items():
d2[cluster].append(point)
Your defaultdict
won't have a cluster 1
in it, but if you know what clusters you expect, then all will be fine with the world (because the empty list will be put in that slot when you try to look there -- this is the "default" part of the defaultdict
):
expected_clusters = [1, 2, 3]
for cluster in expected_clusters:
print(d2[cluster])
FWIW, doing this problem with the builtin filter
is just insanity. However, if you must, something like the following works:
d2 = {}
filter(lambda (pt, cl): d2.setdefault(cl, []).append(pt), d1.items())
Note that I'm using python2.x's unpacking of arguments. For python3.x, you'd need to do something like lambda item: d2.setdefault(item[1], []).append(item[0])
, or, maybe we could do something like this which is a bit nicer:
d2 = {}
filter(lambda pt: d2.setdefault(d1[pt], []).append(pt), d1)
We can do a tiny bit better with the reduce
builtin (at least the reduce
isn't simply a vehicle to create an implicit loop and therefore actually returns the dict we want):
>>> d1 = {1:2,3:3,2:2,4:2,5:2}
>>> reduce(lambda d, k: d.setdefault(d1[k], []).append(k) or d, d1, {})
{2: [1, 2, 4, 5], 3: [3]}
But this is still really ugly python.
Upvotes: 2
Reputation: 1575
>>> d1 = {1:2,3:3,2:2,4:2,5:2}
>>> dict(map(lambda c : (c, [k for k, v in d1.items() if v == c]), d1.values()))
{2: [1, 2, 4, 5], 3: [3]}
Upvotes: 0