【问题标题】:Iterate over itertools.product in different order without ever creating list以不同的顺序迭代 itertools.product 而无需创建列表
【发布时间】:2017-02-16 11:19:09
【问题描述】:

我有一个 iterable 覆盖了巨大的搜索空间。我的计划不是让脚本终止,而是在一定时间后终止它。

现在我需要这个空间的笛卡尔积并在那里搜索。 itertools.product 产生这个订单:

>>> list(itertools.product(range(3), repeat=2))
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

虽然我想以类似于以下的对角线顺序搜索:

[(0, 0), (0, 1), (1, 0), (0, 2), (1, 1), (2, 0), (1, 2), (2, 1), (2, 2)]

sorted 带有一些返回元组元素总和的关键函数将是我的常规方法,但是对于所有数据的排序都需要检查,这在我的情况下是不可行的。有没有办法做到这一点?

这个问题与this one 非常相似,但答案中仍然使用sorted。我也没有很快明白如何将ordered_combinations 调整为ordered_product

【问题讨论】:

  • 输出顺序应该如何查找range(4),repeat=3
  • 问题陈述仅限于repeat=2,因为 OP 是根据方阵 M 的对角线来考虑的,其中行数和列数为 N(在本例中为 3)。偶然itertools.product 产生了矩阵中所有元素位置的列表,并且 OP 试图操纵这些位置以获得预期的输出,但这里真正应该做的是基于类似矩阵的问题陈述的完全不同的解决方案。
  • @Chris_Rands 我猜仍然按元素总和的顺序排列,并且按字典顺序排列为相等的总和。虽然我只对 repeat=2 的情况感兴趣并且我不关心对角线的方向,例如,我不关心是 (0,1) 还是 (1,0) 先出现。 @ŁukaszRogalski 好吧,这就是我的想象,是的,它不一定是答案的结构(尽管它可能是)。

标签: python algorithm dynamic-programming combinatorics itertools


【解决方案1】:

实际上很容易计算 repeat=2 情况下对角线的索引:

def diagonal_product(inp):
    inp = tuple(inp)
    n = len(inp)
    # upper left triangle
    for i in range(n):
        for j in range(i+1):
            yield inp[i-j], inp[j]
    # lower right triangle
    for i in range(1, n):
        for j in range(n-i):
            yield inp[n-j-1], inp[i+j]

只是为了显示结果:

>>> list(diagonal_product(range(4)))
[(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (3, 0), (2, 1), (1, 2), 
 (0, 3), (3, 1), (2, 2), (1, 3), (3, 2), (2, 3), (3, 3)]

>>> list(diagonal_product(range(3)))
[(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (2, 1), (1, 2), (2, 2)]

函数本身可能比它需要的更复杂(或更慢),但我还没有找到任何适用于这种情况的参考实现。

如果将 range 作为输入,您还可以避免所有索引并只返回索引:

def diagonal_product(n):
    # upper left triangle
    for i in range(n):
        for j in range(i+1):
            yield i-j, j
    # lower right triangle
    for i in range(1, n):
        for j in range(n-i):
            yield n-j-1, i+j

list(diagonal_product(3))
# [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (2, 1), (1, 2), (2, 2)]

【讨论】:

    【解决方案2】:

    这个问题相当于询问如何为给定总和创建所有 n 元组,以获得连续和递增的总和值:

                      (0, 0),               sum == 0
                  (0, 1), (1, 0),           sum == 1
            (0, 2), (1, 1), (2, 0),         sum == 2
                 (1, 2), (2, 1),            sum == 3
                      (2, 2)                sum == 4
    

    对于任何给定的行(具有给定的目标总和),子问题等价于动态规划问题Number of ways to make change for amount NNumber of ways to add up to a sum S with N numbers

    另请参阅 Donald Knuth 在Combinatorial Algorithms 中的文章。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多