2016-01-26 53 views
-4

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

如果我有像下面列出的清单:

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

我怎样才能得到列出的所有组合的列表? 对于data_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_big任意数量的列表。

我很确定这是一个奇特的itertools解决方案,对吧?

+0

跨越不同子列表的字母是否始终是唯一的? – gtlambert

+3

规格不清。定义组合。 – timgeb

+1

应该有20个组合,并且您只显示8个,以便列表要么不完整,要么有未指定的规则。这是什么? – SirParselot

回答

2

我想我破译了一个问题:

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_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']] 
+0

谢谢你的解决方案! “so_called_combs”:D你会怎么称呼它? – coroner

+0

@coroner我不知道,你用它做什么?我不会把它称为组合,因为这意味着其他的东西(参见'itertools.combinations') – L3viathan

+0

这并不是所有的“组合”它缺少'['a','e','w']'和23更多 – SirParselot

1

这里是另一种方式使用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'] 

这并不关心,如果有一个以上的元素不止一个元素

from itertools import permutations, chain 

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): 
    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 

    return True 

#If you really want lists just change the first x to list(x) 
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'], 61 more... 

我用排列组合来代替的原因是因为('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')] 
0

对不起,我来晚了党,但在这里,就是看中了“一 - 班轮”使用itertools和非常有用的新的Python 3.5拆包概括(分割多行的可读性)(其中,顺便说一下,可迭代是类型比,也就是说之间进行转换的一个显著更快和更可读的方式,主叫list明确)---并假设独特元素:

>>> 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']] 

在发电机中使用的下一个和最后两行当然只是语法的不必要的利用来将表达式放入一行,而我希望人们不要将其作为良好编码习惯的一个例子。

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

相关问题