我正在尝试制定一种通用方法来生成多个范围或列表的所有组合,例如,
[range(0, 2), range(2, 5), range(4, 6), range(2, 3)]
,
它应该返回一个 2x3x2x1 = 12 元素列表。
[[0, 2, 4, 2],
[0, 2, 5, 2],
[0, 3, 4, 2],
[0, 3, 5, 2],
[0, 4, 4, 2],
[0, 4, 5, 2],
[1, 2, 4, 2],
[1, 2, 5, 2],
[1, 3, 4, 2],
[1, 3, 5, 2],
[1, 4, 4, 2],
[1, 4, 5, 2]]
到目前为止,这里一切都很好。当我对其进行硬编码时,通过执行
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
x.append( ( a + [b] for a in x[-1] for b in rgs[2]) )
x.append( ( a + [b] for a in x[-1] for b in rgs[3]) )
我得到了很好的结果。然而,当我尝试概括它时,通过这样做
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
for i in range(1,len(rgs)-1):
x.append( ( a + [b] for a in x[-1] for b in rgs[i+1]) )
我获得一个 6 元素列表:
[[0, 2, 2, 2],
[0, 3, 2, 2],
[0, 4, 2, 2],
[1, 2, 2, 2],
[1, 3, 2, 2],
[1, 4, 2, 2]]
此外,我注意到前两个之后生成的所有范围都使用 rgs[-1]
中的范围。而不是正确的。我很难理解为什么会发生这种情况,因为我相信这两个代码示例是相同的,只是后者是任意大量范围的更通用形式。
最佳答案
您可以使用itertools.product
输出元组列表
输入:
import itertools
a= [range(0, 2), range(2, 5), range(4, 6), range(2, 3)]
list(itertools.product(*a))
输出:
[(0, 2, 4, 2),
(0, 2, 5, 2),
(0, 3, 4, 2),
(0, 3, 5, 2),
(0, 4, 4, 2),
(0, 4, 5, 2),
(1, 2, 4, 2),
(1, 2, 5, 2),
(1, 3, 4, 2),
(1, 3, 5, 2),
(1, 4, 4, 2),
(1, 4, 5, 2)]
运行第一个代码时我没有得到相同的结果。我不得不稍微改变一下:
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
x.append( ( a + [b] for a in x[-1] for b in rgs[2]) )
x = list( a + [b] for a in x[-1] for b in rgs[3])
大多数不了解 itertools 的人都会这样做:
x=[]
for i0 in rgs[0]:
for i1 in rgs[1]:
for i2 in rgs[2]:
for i3 in rgs[3]:
x.append([i0,i1,i2,i3])
或者使用列表理解(不要这样做,它看起来非常困惑):
[[i0,i1,i2,i3] for i3 in rgs[3] for i2 in rgs[2] for i1 in rgs[1] for i0 in rgs[0]]
关于Python 生成器的起源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52546783/