简体   繁体   中英

Print a list of every combination of dictionary keys with the associated sum of the key values to the right

I have several dictionaries and I want to print a table where each row is a unique combination of the keys in all dictionaries. For each row, I also want to print the sum of the values for the keys in that particular combination.

So, if I have these dictionaries:

dict1 = {"Main": 8, "Optional": 6, "Obscure": 4}
dict2 = {"Global": 8, "Regional": 4, "Local": 2}
...

The output would look like this (sorted by sum highest to lowest):

Main, Global, 16
Optional, Global, 14
Main, Regional, 12
Obscure, Global, 12
Main, Local, 10
Optional, Regional, 10
Optional, Local, 8
Obscure, Regional, 8
Obscure, Local, 6

From what I've read, itertools.product will be what I'm looking for, but none of the existing questions are quite my use case and I'm struggling to even get started.

Any help would be appreciated.

Thanks

I think this would be something like:

import itertools

dict1 = {"Main": 8, "Optional": 6, "Obscure": 4}
dict2 = {"Global": 8, "Regional": 4, "Local": 2}

merged = {'{}, {}'.format(prod[0], prod[1]): dict1[prod[0]] + dict2[prod[1]] 
          for prod in itertools.product(dict1, dict2)}

for k, v in merged.items():
    print('{}: {}'.format(k, v))

Output:

Optional, Regional: 10
Main, Regional: 12
Optional, Local: 8
Main, Global: 16
Optional, Global: 14
Main, Local: 10
Obscure, Regional: 8
Obscure, Global: 12
Obscure, Local: 6

Use product from itertools on the dictionary items() where you can get the both key and value at the same time, and with the combination of key-value pairs you can construct the final result pretty straightforwardly:

from itertools import product
sorted([(k1, k2, v1+v2) for (k1, v1), (k2, v2) in product(dict1.items(), dict2.items())], \
       key = lambda x: x[2], reverse=True)

# [('Main', 'Global', 16),
#  ('Optional', 'Global', 14),
#  ('Obscure', 'Global', 12),
#  ('Main', 'Regional', 12),
#  ('Main', 'Local', 10),
#  ('Optional', 'Regional', 10),
#  ('Obscure', 'Regional', 8),
#  ('Optional', 'Local', 8),
#  ('Obscure', 'Local', 6)]

You've read right. Just add sorted() :

from itertools import product
from operator import itemgetter

results = [(k1, k2, dict1[k1] + dict2[k2])
           for k1, k2 in product(dict1.keys(), dict2.keys())]

for k1, k2, sum_ in sorted(results, key=itemgetter(2), reverse=True): 
    print(k1, k2, sum_, sep=', ')

This method is built to support a variable amount of dictionaries. You pass your dictionaries to the get_product_sums() method, which then creates a cartesian product from the tuple of dictionaries.

We then iterate through our new subitem to calculate sums by doing a look up in our flattened which is just a 1D dictionary now. We then sort by the sum, and return a sorted list of tuples for our final result .

from itertools import product

def get_product_sums(* args):
    result = []
    flattened = {k:v for d in args for k, v in d.items()}
    for subitem in product(* args, repeat=1):
        data = subitem + (sum(flattened[key] for key in subitem),)  
        result.append(data)
    return sorted(result, key=lambda x: x[-1], reverse=True)

Sample Output:

>>> dict1 = {"Global": 8, "Regional": 4, "Local": 2} 
>>> dict2 = {"Main": 8, "Optional": 6, "Obscure": 4}
>>> for item in get_product_sums(dict1, dict2):
...     print ', '.join(str(element) for element in item)
Global, Main, 16
Global, Optional, 14
Global, Obscure, 12
Regional, Main, 12
Local, Main, 10
Regional, Optional, 10
Local, Optional, 8
Regional, Obscure, 8
Local, Obscure, 6

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM