Search code examples
pythonpython-itertools

Iterating through all combinations across many iterables


for item1 in dict[1]:
   for item2 in dict[2]:
     for item3 in dict[3]:
        and so on

Let's say there are n keys in dict. Is there a way to generate n items at a time with a one-liner using itertools?

in other words can I replicate the above code with something in itertools?


Solution

  • Use itertools.product():

    from itertools import product
    
    for combo in product(*somedict.values()):
    

    Note that the values are returned in current dictionary order, which is arbitrary. If you need a specific ordering of the keys, you'll need to provide that order:

    keys = ('foo', 'bar', 'baz')
    for combo in product(*(somedict[k] for k in keys)):
    

    If you wanted a dictionary with the same keys again, use zip():

    for combo in product(*somedict.values()):
        newdict = dict(zip(somedict.keys(), combo))
    

    Demo:

    >>> from itertools import product
    >>> somedict = {'foo': [1, 2], 'bar': ['a', 'b', 'c'], 'baz': [42, 81]}
    >>> for combo in product(*somedict.values()):
    ...     print combo
    ... 
    (42, 1, 'a')
    (42, 1, 'b')
    (42, 1, 'c')
    (42, 2, 'a')
    (42, 2, 'b')
    (42, 2, 'c')
    (81, 1, 'a')
    (81, 1, 'b')
    (81, 1, 'c')
    (81, 2, 'a')
    (81, 2, 'b')
    (81, 2, 'c')
    >>> for combo in product(*somedict.values()):
    ...     print dict(zip(somedict.keys(), combo))
    ... 
    {'bar': 'a', 'foo': 1, 'baz': 42}
    {'bar': 'b', 'foo': 1, 'baz': 42}
    {'bar': 'c', 'foo': 1, 'baz': 42}
    {'bar': 'a', 'foo': 2, 'baz': 42}
    {'bar': 'b', 'foo': 2, 'baz': 42}
    {'bar': 'c', 'foo': 2, 'baz': 42}
    {'bar': 'a', 'foo': 1, 'baz': 81}
    {'bar': 'b', 'foo': 1, 'baz': 81}
    {'bar': 'c', 'foo': 1, 'baz': 81}
    {'bar': 'a', 'foo': 2, 'baz': 81}
    {'bar': 'b', 'foo': 2, 'baz': 81}
    {'bar': 'c', 'foo': 2, 'baz': 81}