【问题标题】:How to get Cartesian product in Python using a generator?如何使用生成器在 Python 中获取笛卡尔积?
【发布时间】:2020-08-24 08:46:51
【问题描述】:

我正在尝试获取多个数组的笛卡尔积,但数组非常大,我正在尝试优化内存使用。我尝试使用下面的代码来实现一个生成器,但它只是返回某个位置有一个生成器。

import itertools

x = [[1,2],[3,4]]

def iter_tools(*array):
    yield list(itertools.product(*array))

print(iter_tools(*x))

当我尝试相同的代码但使用 return 而不是 yield 时,它工作正常。如何通过实现生成器获得笛卡尔积?

【问题讨论】:

  • 您的生成器立即实现了整个产品,破坏了整个目的。在任何的情况下,itertools.product(*array) 已经是一个高效的迭代器。无需将其包装在生成器中。所以只需使用itertools.product(*array)。您的生成器确实有效,生成器函数返回生成器。看来您有一个根本性的误解。
  • @juanpa 谢谢!我发布了an answer 部分基于您的评论。

标签: python iteration generator cartesian-product


【解决方案1】:

底线,itertools.product 已经是 iterator。你不需要自己写。 (generator 是一种迭代器。)例如:

>>> x = [[1, 2], [3, 4]]
>>> p = itertools.product(*x)
>>> next(p)
(1, 3)
>>> next(p)
(1, 4)

现在,解释一下,您似乎误解了一些基本的东西。生成器函数返回generator iterator。这就是您从印刷品中看到的:

>>> iter_tools(*x)
<generator object iter_tools at 0x7f05d9bc3660>

使用list() 将迭代器强制转换为列表。

>>> list(iter_tools(*x))
[[(1, 3), (1, 4), (2, 3), (2, 4)]]

注意它是一个嵌套列表。那是因为您的 iter_tools 产生一个列表,然后没有其他任何东西。在那一点上,这部分没有意义,因为将itertools.product 转换为列表会破坏迭代器的全部目的-lazy evaluation。如果你真的想从迭代器中产生值,你可以使用yield from

def iter_tools(*array):
    yield from itertools.product(*array)

在这种情况下iter_tools 毫无意义,但如果您的实际iter_tools 更复杂,这可能就是您真正想要的。

另见:


这个答案部分基于juanpa.arrivillagacomment

【讨论】:

    【解决方案2】:

    生成器的想法是您不会像调用list(itertools.product(*array)) 那样同时进行所有计算。所以你要做的就是一一生成结果。比如这样:

    def iter_tools(*array):
        for i in array[0]:
            for j in array[1]:
                yield (i, j)
    
    

    然后你可以像这样对每个结果元组做一些事情:

    for tup in iter_tools(*x):
        print(tup)
    

    当然,您可以轻松地调整生成器,使其在每次调用时生成每一行或每一列。

    或者,如果您对 itertools 提供的功能感到满意:

    for i in itertools.product(*x):
        print(i)
    

    您需要什么取决于您的用例。希望能帮到你:)

    【讨论】:

      【解决方案3】:

      如果您想从笛卡尔积中产生单个项目,则需要迭代该产品:

      import itertools
      
      x = [[1,2],[3,4]]
      
      def iter_tools(*array):
          for a in itertools.product(*array):
              yield a
      
      for a in iter_tools(*x):
          print(a)
      
      

      【讨论】:

      • itertools.product 已经是一个迭代器,这使得 iter_tools 毫无意义。
      猜你喜欢
      • 2016-10-08
      • 2021-05-06
      • 2011-12-26
      • 2021-09-05
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      相关资源
      最近更新 更多