在python中组合n个列表的所有元素

在python中组合n个列表的所有元素,python,list,itertools,Python,List,Itertools,关于在python中组合和合并列表有很多问题和答案,但我还没有找到一种方法来创建所有元素的完整组合 如果我有如下列表: data_small = [ ['a','b','c'], ['d','e','f'] ] data_big = [ ['a','b','c'], ['d','e','f'], ['u','v','w'], ['x','y','z'] ] 如何获得包含所有组合的列表列表? 对于数据\u small这应该是: [ [a,b,c], [d,b,c], [a,b,f], [a,e,

关于在python中组合和合并列表有很多问题和答案,但我还没有找到一种方法来创建所有元素的完整组合

如果我有如下列表:

data_small = [ ['a','b','c'], ['d','e','f'] ]
data_big = [ ['a','b','c'], ['d','e','f'], ['u','v','w'], ['x','y','z'] ]
如何获得包含所有组合的列表列表? 对于
数据\u small
这应该是:

[ [a,b,c], [d,b,c], [a,b,f], [a,e,c],
  [d,e,c], [d,b,f], [a,e,f], [d,e,f], ... ]
这也适用于任意数量的相同长度的列表,如
data\u big


我很确定有一种奇特的itertools解决方案,对吗?

我想我已经破解了这个问题:

def so_called_combs(data):
    for sublist in data:
        for sbl in data:
            if sbl==sublist:
                yield sbl
                continue
            for i in range(len(sublist)):
                c = sublist[:]
                c[i] = sbl[i]
                yield c
如果我理解正确,则返回所需列表:

对于数据中的每个列表,每个元素(但一次只能替换一个)都将替换为其他每个列表中的相应元素(相同位置)

对于
data\u big
,返回:

[['a', 'b', 'c'], ['d', 'b', 'c'], ['a', 'e', 'c'], ['a', 'b', 'f'],
 ['u', 'b', 'c'], ['a', 'v', 'c'], ['a', 'b', 'w'], ['x', 'b', 'c'],
 ['a', 'y', 'c'], ['a', 'b', 'z'], ['a', 'e', 'f'], ['d', 'b', 'f'],
 ['d', 'e', 'c'], ['d', 'e', 'f'], ['u', 'e', 'f'], ['d', 'v', 'f'], 
 ['d', 'e', 'w'], ['x', 'e', 'f'], ['d', 'y', 'f'], ['d', 'e', 'z'],
 ['a', 'v', 'w'], ['u', 'b', 'w'], ['u', 'v', 'c'], ['d', 'v', 'w'],
 ['u', 'e', 'w'], ['u', 'v', 'f'], ['u', 'v', 'w'], ['x', 'v', 'w'],
 ['u', 'y', 'w'], ['u', 'v', 'z'], ['a', 'y', 'z'], ['x', 'b', 'z'],
 ['x', 'y', 'c'], ['d', 'y', 'z'], ['x', 'e', 'z'], ['x', 'y', 'f'],
 ['u', 'y', 'z'], ['x', 'v', 'z'], ['x', 'y', 'w'], ['x', 'y', 'z']]

这里是使用itertools置换和链函数的另一种方法。您还需要检查索引是否对齐且长度是否相同,以及是否替换了多个元素

from itertools import *
data_small = [ ['a','b','c'], ['d','e','f'] ]
data_big = [ ['a','b','c'], ['d','e','f'], ['u','v','w'], ['x','y','z'] ]

def check(data, sub):
    check_for_mul_repl = []
    for i in data:
        if len(i) != len(data[0]):
            return False

        for j in i:
            if j in sub:
                if i.index(j) != sub.index(j):
                    return False
                else:
                    if i not in check_for_mul_repl:
                        check_for_mul_repl.append(i)
    if len(check_for_mul_repl) <= 2:
        return True
print [x for x in list(permutations(chain(*data_big), 3)) if check(data_big, x)]

['a', 'b', 'c'], ['a', 'b', 'f'], ['a', 'b', 'w'], ['a', 'b', 'z'],
['a', 'e', 'c'], ['a', 'e', 'f'], ['a', 'v', 'c'], ['a', 'v', 'w'],
['a', 'y', 'c'], ['a', 'y', 'z'], ['d', 'b', 'c'], ['d', 'b', 'f'],
['d', 'e', 'c'], ['d', 'e', 'f'], ['d', 'e', 'w'], ['d', 'e', 'z'],
['d', 'v', 'f'], ['d', 'v', 'w'], ['d', 'y', 'f'], ['d', 'y', 'z'],
['u', 'b', 'c'], ['u', 'b', 'w'], ['u', 'e', 'f'], ['u', 'e', 'w'],
['u', 'v', 'c'], ['u', 'v', 'f'], ['u', 'v', 'w'], ['u', 'v', 'z'],
['u', 'y', 'w'], ['u', 'y', 'z'], ['x', 'b', 'c'], ['x', 'b', 'z'],
['x', 'e', 'f'], ['x', 'e', 'z'], ['x', 'v', 'w'], ['x', 'v', 'z'],
['x', 'y', 'c'], ['x', 'y', 'f'], ['x', 'y', 'w'], ['x', 'y', 'z']
我之所以使用排列而不是组合,是因为
('d','b','c')
在组合方面而不是在排列方面等于
('c','b','d')

如果你只是想要组合,那就容易多了。你可以这么做

def check(data) #Check if all sub lists are same length
    for i in data:
        if len(i) != len(data[0]):
            return False
    return True

if check(data_small):
    print list(combinations(chain(*data_small), 3))

[('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'b', 'e'), ('a', 'b', 'f'),
 ('a', 'c', 'd'), ('a', 'c', 'e'), ('a', 'c', 'f'), ('a', 'd', 'e'),
 ('a', 'd', 'f'), ('a', 'e', 'f'), ('b', 'c', 'd'), ('b', 'c', 'e'), 
 ('b', 'c', 'f'), ('b', 'd', 'e'), ('b', 'd', 'f'), ('b', 'e', 'f'),
 ('c', 'd', 'e'), ('c', 'd', 'f'), ('c', 'e', 'f'), ('d', 'e', 'f')]

很抱歉来晚了,但这里有一个奇特的“一行程序”(为了可读性而拆分为多行)使用itertools和非常有用的新Python3.5解包泛化(顺便说一句,与显式调用
list
相比,这是一种在iterable类型之间进行转换的速度更快、可读性更高的方法)--并且假设元素是唯一的:

>>> from itertools import permutations, repeat, chain
>>> next([*map(lambda m: [m[i][i] for i in range(a)],
               {*permutations((*chain(*map(
                   repeat, map(tuple, l), repeat(a - 1))),), a)})]
         for l in ([['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']],)
         for a in (len(l[0]),))
[['g', 'h', 'f'], ['g', 'b', 'i'], ['g', 'b', 'f'],
 ['d', 'b', 'f'], ['d', 'h', 'f'], ['d', 'h', 'i'],
 ['a', 'e', 'c'], ['g', 'e', 'i'], ['a', 'h', 'i'],
 ['a', 'e', 'f'], ['g', 'e', 'c'], ['a', 'b', 'i'],
 ['g', 'b', 'c'], ['g', 'h', 'c'], ['d', 'h', 'c'],
 ['d', 'b', 'c'], ['d', 'e', 'c'], ['a', 'b', 'f'],
 ['d', 'b', 'i'], ['a', 'h', 'c'], ['g', 'e', 'f'],
 ['a', 'e', 'i'], ['d', 'e', 'i'], ['a', 'h', 'f']]
当然,在生成器和最后两行中使用next只是不必要地利用语法将表达式放在一行中,我希望人们不要将其用作良好编码实践的示例

编辑
我刚刚意识到也许我应该给出一个简短的解释。因此,内部部分创建每个子列表的
a-1
副本(转换为元组以进行哈希性和唯一性测试)并将它们链接在一起,以允许
排列
发挥其神奇作用,即创建
a
子列表长度的所有子列表排列。然后将这些子列表转换为一个集合,以消除所有必然出现的重复项,然后一个映射在ea中拉出
i
第th子列表的
i
第th元素ch唯一排列。最后,
a
是第一个子列表的长度,因为假设所有子列表都具有相同的长度。

不同子列表中的字母是否总是唯一的?规格不清楚。定义组合。应该有20个组合,而您只显示了8个组合,因此列表要么不完整,要么不完整未指定的规则。是什么?我理解它们的意思;我认为:不是通常意义上的组合,而是用其他子列表中相应位置的项目替换子列表中的每个位置。根据该定义,结果是有意义的。这是矛盾的。如果@L3viathan是正确的,那么您将只有8个组合离子,但如果你只需要所有的组合,那么你就有20个。谢谢你提供了这个解决方案!“所谓的梳子”:D你怎么称呼它?验尸官我不知道,你用它做什么?我不会叫它组合,因为这意味着其他东西(见
itertools.combines
)这并没有给出所有的“组合”它缺少
['a','e','w']
和23more@SirParselot我把它解释为只替换了一个元素。因为我不知道他们真正想要的是什么,我只能猜测。但是很好的一点。在我们的两个答案之间,我想我们涵盖了所有的角度
>>> from itertools import permutations, repeat, chain
>>> next([*map(lambda m: [m[i][i] for i in range(a)],
               {*permutations((*chain(*map(
                   repeat, map(tuple, l), repeat(a - 1))),), a)})]
         for l in ([['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']],)
         for a in (len(l[0]),))
[['g', 'h', 'f'], ['g', 'b', 'i'], ['g', 'b', 'f'],
 ['d', 'b', 'f'], ['d', 'h', 'f'], ['d', 'h', 'i'],
 ['a', 'e', 'c'], ['g', 'e', 'i'], ['a', 'h', 'i'],
 ['a', 'e', 'f'], ['g', 'e', 'c'], ['a', 'b', 'i'],
 ['g', 'b', 'c'], ['g', 'h', 'c'], ['d', 'h', 'c'],
 ['d', 'b', 'c'], ['d', 'e', 'c'], ['a', 'b', 'f'],
 ['d', 'b', 'i'], ['a', 'h', 'c'], ['g', 'e', 'f'],
 ['a', 'e', 'i'], ['d', 'e', 'i'], ['a', 'h', 'f']]