命名itertools.products中的可迭代对象部分
我最近在了解 itertools
这个模块,听说它非常强大。我特别对 itertools.product()
感兴趣,因为它可以给我所有输入的组合。
不过,我想知道每个输出是来自哪个输入的可迭代对象。例如,一个简单的标准例子是:
itertools.product([1, 2, 3], [1, 2])
如果用户提供的输入是 [1,2,3] 和 [1, 2],我就不知道它们的顺序,所以得到的结果是
(1, 2)
并没有太大帮助,因为我不知道它们的排列顺序。有没有什么方法可以像这样提供输入:
itertools.product(foo = [1, 2, 3], bar = [1, 2])
然后得到像这样的输出:
output['foo'] = 1
output['bar'] = 2
或者
output.foo = 1
output.bar = 2
2 个回答
5
结果总是按照传入的参数顺序排列的,比如在 (1, 2)
中,1
必须来自 [1,2,3]
,而 2
必须来自 [1,2]
。
所以,你的需求可以通过重复使用 itertools.product 来满足:
def named_product(**items):
names = items.keys()
vals = items.values()
for res in itertools.product(*vals):
yield dict(zip(names, res))
23
使用 itertools.product([1, 2, 3], [1, 2])
这个代码,你会得到一系列有序的配对,第一个元素来自 [1,2,3]
,第二个元素来自 [1,2]
。这个结果是一定会这样产生的。
如果你想要给这些配对起个名字,可以把结果转换成一个 命名元组。这样的话,你就可以通过 output.foo
和 output.bar
来访问这些字段。结合KennyTM的想法,使用 **items
,可以把这个功能放在一个快速且节省内存的函数里:
from itertools import product, starmap
from collections import namedtuple
def named_product(**items):
Product = namedtuple('Product', items.keys())
return starmap(Product, product(*items.values()))
下面是一个示例调用:
>>> 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)