2011-12-03 33 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]]] 

はい、それはあなたが提供するサンプル出力はわずかに異なるのですが、その出力には、すべての可能な組み合わせをリストしていませんでした。

何が必要なの単純な組み合わせであれば(それはあなたのサンプル出力に表示される、大きさせずに)私は、これらの他のバージョンを試してみてください、その後、前に各サイズの実際のリストを組み合わせのサイズを一覧表示していますコード:itertoolsモジュールの戻りイテレータから

[[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

機能:

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はこの値を保持します。これらをリストに変換するために必要なのは、結果としてlist()です。

しかし、itertools.combinationsを3回(1回の長さごとに)呼び出す必要があるため、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]] 

やリストなどの単一の項目を残して:あなたは、ループの内側にitertools.combinationsを使用して、あなたの問題を解決することができ

+0

私はこれを使用しようとしましたが、 NoneTypesでiterを使用しないでください。 – Charles

+0

両方のソリューションがまだタプルのリストを返しています。 – juliomalegria

+0

うん、リストのリストが必要です。タプルはありません。 itertoolsを使用せずに問題を解決する方法はありますか? – Charles

5

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

EDIT:組み合わせの最初のパラメータは反復可能であり、2番目のパラメータは結果のタプルの長さです(この場合は1からlen(l)になります)。 itertoolsモジュールが実際に代わり、リストの発電を返しますが、http://docs.python.org/library/itertools.html#itertools.combinations

6

:あなたは多数を生成している場合は特に

  • ジェネレータは、(多くの場合、リストよりも効率的である組み合わせについて

    詳細組み合わせ)

  • 本当に必要なときにいつでも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]] 

以前にジェネレータを使用していない場合は、ジェネレータをループのようにループしていることに注意してくださいこのようなトン、:

# 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), []) 

オンライナーが必要な場合。

関連する問題