Name parts of iterables in itertools.products

2020-07-11 08:21发布

I've been reading about itertools, which seems to be a very powerful module. I am particularly interested in itertools.product() which appears to give me all of the combinations of the iterable inputs.

However, I would like to know which of the input iterables each of the outputs are coming from. For example, a simple standard example is:

itertools.product([1, 2, 3], [1, 2])

If the user provided the inputs of [1,2,3], [1, 2] I won't know which order they came in, so getting a result of

(1, 2)

isn't much help, as I don't know which way round they will be. Is there some way of providing input like:

itertools.product(foo = [1, 2, 3], bar = [1, 2])

and then getting outputs like:

output['foo'] = 1
output['bar'] = 2

or

output.foo = 1
output.bar = 2

2条回答
看我几分像从前
2楼-- · 2020-07-11 08:47

The result will always be ordered according to the argument order of product, i.e. in (1, 2) the 1 must come from [1,2,3] and the 2 must come from [1,2].

Therefore, your requirement can be satisfied by reusing itertools.product:

def named_product(**items):
    names = items.keys()
    vals = items.values()
    for res in itertools.product(*vals):
        yield dict(zip(names, res))
查看更多
女痞
3楼-- · 2020-07-11 08:53

The output of itertools.product([1, 2, 3], [1, 2]) is a series of ordered pairs whether the first element comes from [1,2,3] and the second element from [1,2]. This is guaranteed behavior.

If field names are desired, you can cast the result to a named tuple. As you requested, the named tuple lets you access the fields with output.foo and output.bar. Incorporating KennyTM's idea of using **items, it can be packaged in a single function that is fast and memory efficient:

from itertools import product, starmap
from collections import namedtuple

def named_product(**items):
    Product = namedtuple('Product', items.keys())
    return starmap(Product, product(*items.values()))

Here's an example call:

>>> for output in named_product(foo=[1,2,3], bar=[1,2]):
        print output

Product(foo=1, bar=1)
Product(foo=1, bar=2)
Product(foo=2, bar=1)
Product(foo=2, bar=2)
Product(foo=3, bar=1)
Product(foo=3, bar=2)
查看更多
登录 后发表回答