简体   繁体   中英

How do I iterate through a dictionary of lists and pair each iteration with an item from all the keys?

I need to iterate through a dictionary of lists, not knowing how many lists the dictionary will have, but still pair off each list value with any other list value produced from another key in the dictionary (if another one exists). I have the following code:

def loop_rec(codes, currentcode={}):
    if len(codes.keys())>1:
        for key in sorted(codes):
            codespop = dict(codes)
            loop = codespop.pop(key)
            for x in loop:
                currentcode[key]=x
                loop_rec(codespop,currentcode)
            break
    else:
        for key in codes.keys():
            loop = codes[key]
            for x in loop:
                currentcode[key]=x
                print currentcode

So if I have the following dictionary:

codes = {"coarse":range(4),"fine":range(2)}

I get this result:

>>> loop_rec(codes)
{'fine': 0, 'coarse': 0}
{'fine': 1, 'coarse': 0}
{'fine': 0, 'coarse': 1}
{'fine': 1, 'coarse': 1}
{'fine': 0, 'coarse': 2}
{'fine': 1, 'coarse': 2}
{'fine': 0, 'coarse': 3}
{'fine': 1, 'coarse': 3}

This is a brute force method and would like a more "Pythonic" way of doing this. I searched around a lot for something equivalent, but most methods don't result in the coarse and fine values being together for each iteration. Also would prefer it loop through coarse first, but the sorted command isn't working.

EDIT: Just realized the sorted command is working, the printout just isn't sorted. I don't care if it is printed in order.

If I understand your question correctly, you want to take the cartesian product of all of the lists that are the values of a dict. You can use itertools.product to accomplish this.

import itertools
def dict_product(d):
    list_of_dicts = []
    for values in itertools.product(*d.values()):
        item = dict(zip(d.keys(),values))
        list_of_dicts.append(item)
    return list_of_dicts


codes = {"coarse":range(4),"fine":range(2),"zesty":range(3)}
for item in dict_product(codes):
    print(item)

Result:

{'zesty': 0, 'fine': 0, 'coarse': 0}
{'zesty': 0, 'fine': 0, 'coarse': 1}
{'zesty': 0, 'fine': 0, 'coarse': 2}
{'zesty': 0, 'fine': 0, 'coarse': 3}
{'zesty': 0, 'fine': 1, 'coarse': 0}
{'zesty': 0, 'fine': 1, 'coarse': 1}
{'zesty': 0, 'fine': 1, 'coarse': 2}
{'zesty': 0, 'fine': 1, 'coarse': 3}
{'zesty': 1, 'fine': 0, 'coarse': 0}
{'zesty': 1, 'fine': 0, 'coarse': 1}
{'zesty': 1, 'fine': 0, 'coarse': 2}
{'zesty': 1, 'fine': 0, 'coarse': 3}
{'zesty': 1, 'fine': 1, 'coarse': 0}
{'zesty': 1, 'fine': 1, 'coarse': 1}
{'zesty': 1, 'fine': 1, 'coarse': 2}
{'zesty': 1, 'fine': 1, 'coarse': 3}
{'zesty': 2, 'fine': 0, 'coarse': 0}
{'zesty': 2, 'fine': 0, 'coarse': 1}
{'zesty': 2, 'fine': 0, 'coarse': 2}
{'zesty': 2, 'fine': 0, 'coarse': 3}
{'zesty': 2, 'fine': 1, 'coarse': 0}
{'zesty': 2, 'fine': 1, 'coarse': 1}
{'zesty': 2, 'fine': 1, 'coarse': 2}
{'zesty': 2, 'fine': 1, 'coarse': 3}

In this example, the iteration order is coarse-fine-zesty, but this behavior is not guaranteed. In CPython 3.6 and higher, dictionaries are ordered, but this is an implementation detail and may change in the future.

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