简体   繁体   English

参数数量未知的手动产品

[英]Manual product with unknown number of arguments

The following examples give the same result: 以下示例给出了相同的结果:

A. 一种。

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

B. B.

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

How can I calculate the cartesian product like in example A when I don't know the number of arguments n? 当我不知道参数n时如何计算例A中的笛卡尔积?

REASON I'm asking this: 原因我问这个:

Consider this piece of code: 考虑这段代码:

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

The values of the strategies dictionary are list of tuples, help is an auxiliary variable (a list with the same length of every alloc ) and coalitions is another dictionary that assigns to the tuples in help some numeric value. strategies词典的值是元组列表, help是辅助变量(每个alloc具有相同长度的列表),而coalitions是另一个在help中分配给元组一些数值的词典。

Since strategies values are sorted, I know that the if statement won't be true anymore after a certain alloc . 由于对策略值进行了排序,因此我知道,在某个alloc之后,if语句将不再成立。 Since allocations is a pretty big list, I would avoid tons of comparisons and tons of sums if I could use the example algorithm A. 由于分配是一个很大的列表,因此,如果可以使用示例算法A,我将避免大量的比较和大量的求和。

You can do: 你可以做:

items = ["abcd","xy"]

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

The list items can contain an arbitrary number of strings and it'll the calculation with product will provide you with the Cartesian product of those strings. 列表items可以包含任意数量的字符串,使用product进行计算将为您提供这些字符串的笛卡尔乘积。

Note that you don't have to turn it into a list - you can iterate over it and stop when you no longer wish to continue: 请注意,您不必将其变成列表-您可以对其进行迭代,并在不再希望继续时停止:

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

If you just want to abort the allocations after you hit a certain condition, and you want to avoid generating all the elements from the cartesian product for those, then simply don't make a list of all combinations in the first place. 如果您只是想在达到特定条件后中止分配,并且想要避免从笛卡尔乘积中为这些元素生成所有元素,那么根本就不用列出所有组合。

itertools.product is lazy that means that it will only generate a single value of the cartesian product at a time. itertools.product惰性的 ,这意味着它一次只会生成一个笛卡尔积的单个值。 So you never need to generate all elements, and you also never need to compare the elements then. 因此,您无需生成所有元素,也不需要再比较这些元素。 Just don't call list() on the result as that would iterate the whole sequence and store all possible combinations in memory: 只是不要在结果上调用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

It's just important to note how itertools.product generates the values, what pattern it follows. 重要的是要注意itertools.product如何生成值,遵循的模式。 It's basically equivalent to the following: 它基本上等效于以下内容:

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

So you get an increasing pattern from the left side of your iterables. 因此,您从可迭代对象的左侧获得越来越多的模式。 So make sure that you order the iterables in a way that you can correctly specify a break condition. 因此,请确保以正确指定中断条件的方式订购可迭代对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM