是否有任何 pythonic 方法来生成多个列表之间的组合? (类似于笛卡尔积,但更复杂)
例子:
a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]
# ...
# there are more than 3 lists
预期输出:
1. [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
2. [(1, 4, 8), (2, 5, 7), (3, 6, 9)]
3. [(1, 4, 9), (2, 5, 7), (3, 6, 8)]
4. [(1, 5, 7), (2, 4, 8), (3, 6, 9)]
5. ...
更新:
感谢您的快速回复~!!
澄清问题:
结果都是列表a、b、c的笛卡尔积的不重复组合。
可以通过另一种丑陋的方法来完成:
1) 生成整个笛卡尔积列表
from itertools import product, combinations, chain
t = list(product(a, b, c))
2)使用组合产生所有可能的结果
p = list(combinations(t, 3))
3)过滤重复条件
cnt = len(list(chain(a, b, c)))
f = [x for x in p if len(set(chain(*x))) == cnt]
更新2:
通过丑陋的方法生成的预期结果:
((1, 4, 7), (2, 5, 8), (3, 6, 9))
((1, 4, 7), (2, 5, 9), (3, 6, 8))
((1, 4, 7), (2, 6, 8), (3, 5, 9))
((1, 4, 7), (2, 6, 9), (3, 5, 8))
((1, 4, 8), (2, 5, 7), (3, 6, 9))
((1, 4, 8), (2, 5, 9), (3, 6, 7))
((1, 4, 8), (2, 6, 7), (3, 5, 9))
((1, 4, 8), (2, 6, 9), (3, 5, 7))
((1, 4, 9), (2, 5, 7), (3, 6, 8))
((1, 4, 9), (2, 5, 8), (3, 6, 7))
((1, 4, 9), (2, 6, 7), (3, 5, 8))
((1, 4, 9), (2, 6, 8), (3, 5, 7))
((1, 5, 7), (2, 4, 8), (3, 6, 9))
((1, 5, 7), (2, 4, 9), (3, 6, 8))
((1, 5, 7), (2, 6, 8), (3, 4, 9))
((1, 5, 7), (2, 6, 9), (3, 4, 8))
((1, 5, 8), (2, 4, 7), (3, 6, 9))
((1, 5, 8), (2, 4, 9), (3, 6, 7))
((1, 5, 8), (2, 6, 7), (3, 4, 9))
((1, 5, 8), (2, 6, 9), (3, 4, 7))
((1, 5, 9), (2, 4, 7), (3, 6, 8))
((1, 5, 9), (2, 4, 8), (3, 6, 7))
((1, 5, 9), (2, 6, 7), (3, 4, 8))
((1, 5, 9), (2, 6, 8), (3, 4, 7))
((1, 6, 7), (2, 4, 8), (3, 5, 9))
((1, 6, 7), (2, 4, 9), (3, 5, 8))
((1, 6, 7), (2, 5, 8), (3, 4, 9))
((1, 6, 7), (2, 5, 9), (3, 4, 8))
((1, 6, 8), (2, 4, 7), (3, 5, 9))
((1, 6, 8), (2, 4, 9), (3, 5, 7))
((1, 6, 8), (2, 5, 7), (3, 4, 9))
((1, 6, 8), (2, 5, 9), (3, 4, 7))
((1, 6, 9), (2, 4, 7), (3, 5, 8))
((1, 6, 9), (2, 4, 8), (3, 5, 7))
((1, 6, 9), (2, 5, 7), (3, 4, 8))
((1, 6, 9), (2, 5, 8), (3, 4, 7))
最佳答案
您想要的不是组合,而是排列。 3 个元素有 6 个排列,2 组排列的笛卡尔积有 36。PM 2Ring 最初怀疑你想要所有这 3 个排列,因为你的问题没有说明。如果您问题中的代码产生了所需的输出,则意味着您希望置换 b
和 c
而不是 a
。最初,我编写了计算所有 a
、b
和 c
排列的代码。但是,由于 a
不需要置换,我们只需将它包装在一个列表中。这使我们非常接近所需的输出:
import itertools as it
a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]
for i in it.product([tuple(a)], it.permutations(b), it.permutations(c)):
print(i)
输出为以
开头的36行((1, 2, 3), (4, 5, 6), (7, 8, 9))
((1, 2, 3), (4, 5, 6), (7, 9, 8))
((1, 2, 3), (4, 5, 6), (8, 7, 9))
它已经与您想要的格式几乎相同,但索引已转置,因此 o[x][y]
将匹配您的 o[y][x]
所需的输出。我们使用一些 zip
magic转置它们。另外,此函数现在适用于任意数量的参数:
import itertools as it
a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]
def funnyperms(first, *rest):
for i in it.product([first], *(it.permutations(j) for j in rest)):
yield tuple(zip(*i))
for i in funnyperms(a, b, c):
print(i)
输出是
((1, 4, 7), (2, 5, 8), (3, 6, 9))
((1, 4, 7), (2, 5, 9), (3, 6, 8))
((1, 4, 8), (2, 5, 7), (3, 6, 9))
((1, 4, 8), (2, 5, 9), (3, 6, 7))
((1, 4, 9), (2, 5, 7), (3, 6, 8))
((1, 4, 9), (2, 5, 8), (3, 6, 7))
((1, 4, 7), (2, 6, 8), (3, 5, 9))
((1, 4, 7), (2, 6, 9), (3, 5, 8))
((1, 4, 8), (2, 6, 7), (3, 5, 9))
((1, 4, 8), (2, 6, 9), (3, 5, 7))
((1, 4, 9), (2, 6, 7), (3, 5, 8))
((1, 4, 9), (2, 6, 8), (3, 5, 7))
((1, 5, 7), (2, 4, 8), (3, 6, 9))
((1, 5, 7), (2, 4, 9), (3, 6, 8))
((1, 5, 8), (2, 4, 7), (3, 6, 9))
((1, 5, 8), (2, 4, 9), (3, 6, 7))
((1, 5, 9), (2, 4, 7), (3, 6, 8))
((1, 5, 9), (2, 4, 8), (3, 6, 7))
((1, 5, 7), (2, 6, 8), (3, 4, 9))
((1, 5, 7), (2, 6, 9), (3, 4, 8))
((1, 5, 8), (2, 6, 7), (3, 4, 9))
((1, 5, 8), (2, 6, 9), (3, 4, 7))
((1, 5, 9), (2, 6, 7), (3, 4, 8))
((1, 5, 9), (2, 6, 8), (3, 4, 7))
((1, 6, 7), (2, 4, 8), (3, 5, 9))
((1, 6, 7), (2, 4, 9), (3, 5, 8))
((1, 6, 8), (2, 4, 7), (3, 5, 9))
((1, 6, 8), (2, 4, 9), (3, 5, 7))
((1, 6, 9), (2, 4, 7), (3, 5, 8))
((1, 6, 9), (2, 4, 8), (3, 5, 7))
((1, 6, 7), (2, 5, 8), (3, 4, 9))
((1, 6, 7), (2, 5, 9), (3, 4, 8))
((1, 6, 8), (2, 5, 7), (3, 4, 9))
((1, 6, 8), (2, 5, 9), (3, 4, 7))
((1, 6, 9), (2, 5, 7), (3, 4, 8))
((1, 6, 9), (2, 5, 8), (3, 4, 7))
将这些存储到一个集合中并与您的方法产生的值进行比较,证明它们具有相同的输出:
print(set(funnyperms(a, b, c)) == set(f))
打印True
,Q.E.D.
关于多个列表的python组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45308238/