【问题标题】:Manual product with unknown number of arguments具有未知数量参数的手动产品
【发布时间】:2015-12-26 16:15:20
【问题描述】:

以下示例给出了相同的结果:

一个。

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

B.

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

当我不知道参数 n 的数量时,如何计算示例 A 中的笛卡尔积?

原因我问这个:

考虑这段代码:

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 是辅助变量(每个alloc 长度相同的列表),coalitions 是另一个字典,它分配给帮助中的元组一些数值。

由于策略值已排序,我知道 if 语句在某个 alloc 之后将不再为真。由于分配是一个相当大的列表,如果我可以使用示例算法 A,我会避免大量的比较和大量的总和。

【问题讨论】:

  • 究竟是什么反对为此使用itertools.product
  • 因为在这种情况下,b 的值(我们只考虑每个 alloc 的最后一个元素)将是元组,例如:(0.0.1),(0.0.2),(0.0.3)等等(很长的解释为什么)。相反,coalitions[a] 是一个常数。如果coalitions[a] = 3,我知道在b = (0.0.3)之后,a的所有下一个值一定不能包含在PWC[alloc]中。
  • 我不太明白。您是否想在某个时候取消从笛卡尔积中迭代更多元素?在这种情况下,使用 A 中的列表推导式如何帮助您做到这一点?
  • 对不起,忘记列表理解并考虑嵌套循环(我将立即编辑)。我需要笛卡尔积的所有元素。每个元素都是 PWC 字典中的一个键。每个键重定向到一个列表,并且此类列表的每个第 n 个元素的存在取决于该键的第 n 个元素的总和(它是一个元组的元组)。虽然这样的总和小于某个常数,但该元素必须进入列表中。因为我知道每次迭代的总和都会不断增加,一旦达到极限,我就不需要再检查总和了。

标签: python python-2.7 cartesian-product


【解决方案1】:

你可以这样做:

items = ["abcd","xy"]

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

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

请注意,您不必将其转换为列表 - 您可以对其进行迭代并在您不再希望继续时停止:

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

【讨论】:

  • 我理解这个问题的方式是,OP 明确要求一种像他们的解决方案 A 一样的方法,即没有itertools.product(出于某种未知原因)。
【解决方案2】:

如果您只是想在达到某个条件后中止分配,并且想避免从笛卡尔积中为它们生成所有元素,那么首先不要列出所有组合。

itertools.productlazy 这意味着它一次只会生成一个笛卡尔积的值。所以你永远不需要生成所有元素,你也永远不需要比较元素。只是不要在结果上调用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)

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

【讨论】:

  • 它基本上是等价的,但并不完全相同(我在文档中阅读了算法)。也许我没有很好地解释这一点(我敢肯定,如果我可以与您面对面交谈会容易得多),但是您给了我一个想法,所以无论如何我都会接受这个答案。但是你能回答我的问题吗?是否可以将方法 A 用于 n 个元素?我不知道是不是pythonic还是在python中直接不可能。
  • 不,你不能真正编写任意深度的嵌套 for 循环。从语法上讲,这是行不通的。你只能像itertools 在内部工作。我所说的“基本等价”是指它在功能上是相同的。 itertools.product 一次只会生成一个结果,不会存储中间结果。
猜你喜欢
  • 2014-05-15
  • 2014-04-20
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多