2015-12-26 16 views
0

下面的例子给出了相同的结果:手册产品与参数数目未知的

A.

product = [] 
for a in "abcd": 
    for b in "xy": 
     product.append((a,b)) 

B.

from itertools import product 
list(product("abcd","xy")) 

我如何计算笛卡尔乘积类似例子A当我不知道参数n的数量?

原因我问这:

考虑这一段代码:

allocations = list(product(*strategies.values())) 
for alloc in allocations: 
    PWC[alloc] = [a for (a,b) in zip(help,alloc) if coalitions[a] >= sum(b)] 

的所述strategies字典的值的元组的列表,help是一个辅助变量(与列表每alloccoalitions是相同的长度是另一个字典,分配给元组帮助某些数值。

由于策略值是排序的,我知道if语句在某个alloc之后不再是真的。由于分配是一个相当大名单,我会避免款项吨比较,并吨,如果我可以使用例如算法A.

+0

究竟是什么反对使用'itertools.product'这个? – poke

+0

因为在这种情况下,b的值(让我们只考虑每个alloc的最后一个元素)将是如下的元组:(0.0.1),(0.0.2),(0.0.3)等(很长时间来解释为什么)。相反,联盟[a]是一个常数。如果联盟[a] = 3,我知道在b =(0.0.3)之后,a的所有下一个值都不能包含在PWC [alloc]中。 – Pigna

+0

我真的不明白。是否要取消在某个点上从笛卡尔产品中迭代更多元素?在那种情况下,如何使用A中的列表理解帮助你完成这项工作? – poke

回答

0

如果你只是想在你之后中止拨款碰到一定的条件,并且你想避免从笛卡尔产品中为这些产生所有元素,那么根本就不要首先列出所有组合的列表。

itertools.product懒惰这意味着它一次只能生成笛卡尔乘积的单个值。所以你永远不需要生成所有的元素,而且你也不需要比较元素。只是不上调用的结果list()因为这会遍历整个序列和所有可能的组合存储在内存中:

allocations = product(*strategies.values()) 
for alloc in allocations: 
    PWC[alloc] = [a for (a,b) in zip(help,alloc) if coalitions[a] >= sum(b)] 

    # check whether you can stop looking at more values from the cartesian product 
    if someCondition(alloc): 
     break 

要注意如何itertools.product生成值这只是重要的是,它遵循什么花样。它基本上等同于以下内容:

for a in firstIterable: 
    for b in secondIterable: 
     for c in thirdIterable: 
      … 
       for n in nthIterable: 
        yield (a, b, c, …, n) 

因此,您会从迭代的左侧获得增加的模式。因此,请确保您以可正确指定中断条件的方式排序迭代。

+0

它基本上是等价的,但不完全相同(我在文档中读取了算法)。也许我没有解释得那么好(我敢肯定,如果我可以面对面地谈谈它会更容易),但是你给了我一个主意,所以我会接受这个答案。但是,请你回答我的问题吗?对于n个元素可以使用方法A吗?我不知道它是pythonic还是python中不可能的。 – Pigna

+0

不,你不能真正写入任意深度的嵌套for循环。这在句法上不起作用。你只能像'itertools'一样在内部工作。而且,“基本上等价”我的意思是它在功能上是相同的。 'itertools.product'只会一次产生一个结果而不存储中间结果。 – poke

1

你可以这样做:

items = ["abcd","xy"] 

from itertools import product 
list(product(*items)) 

列表items可以包含任意数量的的字符串,它将与product计算将为您提供这些字符串的笛卡尔积。

请注意,你不必把它变成一个列表 - 你可以遍历并停止当你不再想继续:

for item in product(*items): 
    print(item) 
    if condition: 
     break 
+1

我明白这个问题的方式,OP明确要求一种方法来做它的解决方案A,即没有'itertools.product'(出于某种未知的原因)。 – poke