2011-12-03 71 views
31

我需要能夠創建一個包含輸入列表的所有可能組合的列表。 例如,列表[1,2,3]應該返回[1 [1,2] [1,3] 2 [2,3] 3 [1,2,3]] 列表不必是以任何特定的順序。在這個網站上,我發現了很多使用itertools的函數,但是當我只需要一個列表時,這些函數就會返回對象。我是一名編碼python的初學者,所以任何想法或想法都將不勝感激。在python中創建列表的所有可能組合

回答

40

只需使用itertools.combinations。例如:

import itertools 

lst = [1, 2, 3] 
combs = [] 

for i in xrange(1, len(lst)+1): 
    combs.append(i) 
    els = [list(x) for x in itertools.combinations(lst, i)] 
    combs.append(els) 

現在combs保持此值:

[1, [[1], [2], [3]], 2, [[1, 2], [1, 3], [2, 3]], 3, [[1, 2, 3]]] 

是的,這是從您提供的樣本輸出略有不同,但在輸出你沒有列出所有可能的組合。

我列出組合的大小前的實際列表中爲每個大小,如果你需要的是簡單的組合(不包括大小,因爲它出現在你的樣品輸出),那麼請嘗試以下其他版本驗證碼:

import itertools 

lst = [1, 2, 3] 
combs = [] 

for i in xrange(1, len(lst)+1): 
    els = [list(x) for x in itertools.combinations(lst, i)] 
    combs.extend(els) 

現在combs保持此值:

[[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 
+0

我導入itertools命令使用 >>> from itertools import * 但我的解釋器告訴我itertools沒有定義。 對不起,所有簡單的問題,我只是非常新的python和編程一般。 – Charles

+0

這不是OP要求的。 – juliomalegria

+0

@ julio.alegria是的,這就是OP的要求,我剛剛編輯我的回答 –

5

從itertools模塊裏返回迭代器的功能。您只需將結果轉換成列表list()即可。但是,由於您需要撥打itertools.combinations三個不同的時間(每個不同長度一次),您可以使用list.extend將迭代器的所有元素添加到最終列表中。

嘗試以下操作:

import itertools 
in_list = [1, 2, 3] 
out_list = [] 
for i in range(1, len(in_list)+1): 
    out_list.extend(itertools.combinations(in_list, i)) 

或列表的理解:

out_list = [c for i in range(len(in_list)) for c in itertools.combinations(in_list, i+1)] 

這將導致以下列表:

[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 

如果想列出,而不是元組,並將單個長度元組轉換爲值,您可以執行以下操作:

out_list = [x[0] if len(x) == 1 else list(x) for x in out_list] 
# [1, 2, 3, [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

或者離開單一的項目,如列表:

+0

我試過用這個,但口譯員說我可以不要在NoneTypes上使用它。 – Charles

+0

你的兩個解決方案仍然返回元組列表。 – juliomalegria

+0

是的,我需要列表的列表,而不是元組。有沒有辦法解決這個問題,而不使用itertools? – Charles

5

你可以解決一個循環內使用itertools.combinations您的問題:

>>> l = [1,2,3] 
>>> comb = [] 
>>> for i in range(len(l)): 
... comb += itertools.combinations(l,i+1) 
... 
>>> comb 
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 

如果你希望他們作爲一個列表:

>>> comb_list = [ list(t) for t in comb ] 
>>> comb_list 
[[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

編輯:組合的第一個參數是可迭代的,第二個參數是所得元組的長度(在這種情況下,從1len(l))。

更多關於組合:http://docs.python.org/library/itertools.html#itertools.combinations

6

itertools模塊確實返回發電機而不是列表,而是:

  • 發電機往往比列表(特別是如果你產生了大量的更有效組合)
  • 當您真的需要時,您始終可以使用list(...)將生成器轉換爲列表。

itertools工作做好chaincombinations功能,但你需要使用的Python 2.6或更高版本:

import itertools 

def all_combinations(any_list): 
    return itertools.chain.from_iterable(
     itertools.combinations(any_list, i + 1) 
     for i in xrange(len(any_list))) 

然後,您可以調用該如此:

# as a generator 
all_combinations([1,2,3]) # --> <itertools.chain at 0x10ef7ce10> 

# as a list 
list(all_combinations([1,2,3])) # --> [(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 

# as a list of lists 
[list(l) for l in all_combinations([1,2,3])] # --> [[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

如果您之前沒有使用過發電機,請注意您將它們循環,就好像它們是一個lis t,如:

# a generator returned instead of list 
my_combinations = all_combinations([1,2,3]) 

# this would also work if `my_combinations` were a list 
for c in my_combinations: 
    print "Combo", c 

""" 
Prints: 
    Combo (1,) 
    Combo (2,) 
    Combo (3,) 
    Combo (1, 2) 
    Combo (1, 3) 
    Combo (2, 3) 
    Combo (1, 2, 3) 
""" 

性能差異可能很大。如果你比較性能,你會看到,發電機快得多創建:

# as a generator 
all_combinations(range(25)) # timing: 100000 loops, best of 3: 2.53 µs per loop 

# as a list 
list(all_combinations(range(25))) # timing: 1 loops, best of 3: 9.37 s per loop 

注意,它仍然需要一段時間,通過在任何情況下,所有的組合迭代,但它可以是一個大爲你贏得勝利,特別是如果你在早期找到你想要的東西的話。

1
l = [1,2,3] 
combs = reduce(lambda x, y: list(itertools.combinations(l, y)) + x, range(len(l)+1), []) 

如果你想要一個oneliner。

相關問題