【问题标题】:Generate lists with elements less or equal to the given list生成元素小于或等于给定列表的列表
【发布时间】:2018-06-25 11:32:28
【问题描述】:

解决以下问题最pythonic的方法是什么?

给定一个列表 A,找到所有列表 B,使得 for i in range(len(A)): B[i]

#Input
A = [1,2,0]
#Output
B = [[0,0,0],
     [1,0,0],
     [1,1,0],
     [1,2,0],
     [0,1,0],
     [0,2,0]]

提前致谢!

【问题讨论】:

  • 听起来像是功课。

标签: python list


【解决方案1】:

您可以使用itertools.product 轻松完成此操作

>>> from itertools import product
>>> A
[1, 2, 0]
>>> B = list(product(*[list(range(e+1)) for e in A]))
>>> B
[(0, 0, 0), (0, 1, 0), (0, 2, 0), (1, 0, 0), (1, 1, 0), (1, 2, 0)]
>>> 

如果你想要 o/p 作为列表的列表,请将元组转换为列表

>>> B = [list(e) for e in B]
>>> B
[[0, 0, 0], [0, 1, 0], [0, 2, 0], [1, 0, 0], [1, 1, 0], [1, 2, 0]]
>>> 

如果你不想使用itertools.product,你可以自定义实现product

>>> B = [[]]; 
>>> for t in [range(e+1) for e in A]:
...     B = [x+[y] for x in B for y in t]
... 
>>> B
[[0, 0, 0], [0, 1, 0], [0, 2, 0], [1, 0, 0], [1, 1, 0], [1, 2, 0]]
>>> 

【讨论】:

  • 太棒了! itertools 在我的列表中。不幸的是,我不允许使用任何辅助库。也许没有它有直接的解决方案?谢谢!
  • 我看不到它适用于任意 len(A)。我错过了什么吗?是否可以将您的第二个解决方案扩展到任何 len(A)?
  • 更新了答案
  • @Sanitha,看起来棒极了!也许你知道,为什么 itertools 的实现比自定义的实现要快得多?谢谢!
【解决方案2】:

这是一个非常聪明的解决方案,不使用itertools,而是使用递归函数调用。无论输入列表的大小如何,它都可以工作:

A = [1,2,0]

def compute(A, B=[], n=0):
    for i in range(A[n]+1):
        A[n] = i
        if A not in B: B.append(A[:])
        if n+1 < len(A): compute(A, B, n+1)  # recursive call here
    return sorted(B)

B = compute(A)

print(B)
# [[0, 0, 0], [0, 1, 0], [0, 2, 0], [1, 0, 0], [1, 1, 0], [1, 2, 0]]

【讨论】:

    【解决方案3】:

    我猜你可以首先生成这些数字的所有唯一组合:

    >>> import itertools
    >>> A = [1,2,0]
    >>> combs = set(itertools.combinations(itertools.chain(*(range(col+1) for col in A)), len(A)))
    >>> combs
    {(0, 1, 1), (0, 2, 0), (1, 1, 0), (1, 2, 0), (0, 0, 2), (0, 1, 2), (1, 0, 0), (0, 0, 1), (1, 0, 1), (1, 1, 2), (0, 0, 0), (0, 1, 0), (1, 0, 2)}
    

    然后选择符合你条件的那些:

    >>> sorted(comb for comb in combs if all(comb[i] <= x for i, x in enumerate(A)))
    [(0, 0, 0), (0, 1, 0), (0, 2, 0), (1, 0, 0), (1, 1, 0), (1, 2, 0)]
    

    但这比使用itertools.product 效率低很多,因为它必须预先生成所有组合,并在最后进行排序以保持顺序。

    【讨论】:

      【解决方案4】:

      这也有效:

      A = [1,2,0]
      
      answers = [[] for element in A]
      answers[0] = [[number,] for number in range(A[0]+1)]
      
      for i in range(len(A)-1):
          for possibility in answers[i]:
              for valid_number in range(A[i+1]+1):
                  answers[i+1].append(possibility + [valid_number, ])
      
      your_answer = answers[-1]
      

      它可能可以写成更紧凑的方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-26
        相关资源
        最近更新 更多