2016-01-26 52 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是第一個子列表的長度,因爲假定所有子列表具有相同的長度。

相關問題