在itertools.products中命名iterables的一部分

时间:2012-02-01 15:09:07

标签: python itertools

我一直在阅读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 个答案:

答案 0 :(得分:16)

itertools.product([1, 2, 3], [1, 2])的输出是一系列有序对,无论第一个元素来自[1,2,3]还是第二个元素来自[1,2]。这是行为保证。

如果需要字段名称,您可以将结果转换为named tuple。根据您的要求,指定的元组可让您访问包含output.foooutput.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)

答案 1 :(得分:5)

结果将始终根据产品的参数顺序排序,即在(1, 2)1必须来自[1,2,3]2必须来自[1,2] 1}}。

因此,重复使用itertools.product:

可以满足您的要求
def named_product(**items):
    names = items.keys()
    vals = items.values()
    for res in itertools.product(*vals):
        yield dict(zip(names, res))