How to get 3 greatest values in a nestet defaultdict in python?

62 Views Asked by At

I have a nested defaultdict like this:

defaultdict(<function __main__.<lambda>()>,
           {'A': defaultdict(<function __main__.<lambda>()>,
                 {'a':2,
                  'b':1,
                  'd':2,
                  'f':1}
            'B': defaultdict(<function __main__.<lambda>()>,
                 {'a':3,
                  'c':4,
                  'e':1}}

I want to get an output like this:

B,c : 4
B,a : 3
A,a : 2

How can I sort a nested defaultdict like this?

Thanks for your help in advance.

4

There are 4 best solutions below

0
this be Shiva On

How about flattening the default dict as a Counter, then calling Counter.most_common?

>>> from collections import Counter, defaultdict
>>> my_dict = defaultdict({...}) 
>>> flattened = {f'{K},{k}':v for K, d in my_dict.items() for k, v in d.items()}
>>> Counter(flattened).most_common(3)
[('B,c', 4), ('B,a', 3), ('A,a', 2)]
2
Timeless On

You can try something like this :

N = 3 # adjust the value here to show/print the N greatest
​
out = sorted([(f"{k1},{k2} : {v2}") for k1, v1 in dico.items() # dico is your d.dict
                      for k2, v2 in v1.items()], key=lambda x: -int(x.split(" : ")[1]))

Output : ​

print(*out[:N], sep="\n")
​
B,c : 4
B,a : 3
A,a : 2
0
Frank Yellin On

I would go about it differently. heapq.nlargest keeps track of the n largest elements with the need to sort them. Unfortunately, it doesn't

import heapq
from operator import itemgetter

items = ((key1, key2, value)
         for key1, d in my_dict.items()
         for key2, value in d.items())
for key1, key2, value in heapq.nlargest(3, items, itemgetter(2)):
   print(f'{key1},{key2}: {value}')
0
Alain T. On

Convert the data to a list of tuples with the number as its first item. Then output the result based on this data sorted in descending order:

Note: a normal dictionary or a defaultdict will behave the same for this

D ={'A': {'a':2,
          'b':1,
          'd':2,
          'f':1},
    'B': {'a':3,
          'c':4,
          'e':1}}

S = ((n,(k1,k2)) for k1,n2 in D.items() for k2,n in n2.items())
for n,k in sorted(S,reverse=True):
    print(",".join(k),":",n)

B,c : 4
B,a : 3
A,d : 2
A,a : 2
B,e : 1
A,f : 1
A,b : 1

If you only need the first 3 values, you can use a subscript on the sorted output (sorted(S,reverse=True)[:3]) or, as others suggested, use heapq.nlargest.