Reputation: 73
I have a dict which goes something like this:
ip = { "1" : ['a','b'],
"2" : ['a','c'],
"3" : ['a','b','c','d'],
"4" : ['a','b','d','e']}
I need to find which of the items in the value sets have maximum number of keys against them and also have the items listed in descending order. The output will be something like :
op = {"a":4,"b":3,"c":2,"d":2,"e":1}
But I read somewhere that the dict cannot be in a sorted fashion, so the output can be a tuple too:
op = [('a', 4), ('b', 3), ('c', 2), ('d', 2), ('e', 1)]
We can iterate through the dict and for each of the items in the value set increment the result in a defaultdict
for that item.
op = defaultdict(int)
for k,v in ip.iteritems():
for item in v:
op[item]+=1
op = sorted(op.items(), key=lambda x: x[1], reverse=True)
Is there a quicker/better way of doing this than the nested for?
Upvotes: 5
Views: 81
Reputation: 61253
Simply use Counter
and chain.from_iterable
In [9]: from collections import Counter
In [10]: from itertools import chain
In [11]: ip = { "1" : ['a','b'],
...: "2" : ['a','c'],
...: "3" : ['a','b','c','d'],
...: "4" : ['a','b','d','e']}
In [12]: Counter(chain.from_iterable(ip.values()))
Out[12]: Counter({'a': 4, 'b': 3, 'c': 2, 'd': 2, 'e': 1})
To remove duplicate value you can always do something like this:
>>> from operator import itemgetter
>>> sorted(Counter(chain.from_iterable(map(set, ip.values()))).items(), key=itemgetter(1), reverse=True)
[('a', 4), ('b', 3), ('c', 2), ('d', 2), ('e', 1)]
Upvotes: 3
Reputation: 48288
This here is not correct:
sorted(op.items(), key=lambda x: x[1], reverse=True)
Try instead:
sorted(ip, key=lambda elementInDict: len(ip[elementInDict]), reverse=True)
example:
for elementInDict in sorted(ip, key=lambda elementInDict: len(ip[elementInDict]), reverse=True):
print elementInDict,
Upvotes: 0