リストの要素の可能なすべての組み合わせを取得するにはどうすればよいですか?


423

15個の数値を含むリストがあり、それらの数値の32,768通りの組み合わせをすべて生成するコードを記述する必要があります。

私が探しているように見えるコード(グーグルによる)をいくつか見つけましたが、コードはかなり不透明で、使用に注意しています。さらに、もっとエレガントな解決策が必要だと感じています。

私に発生する唯一のことは、10進数の整数1〜32768をループしてバイナリに変換し、バイナリ表現をフィルターとして使用して適切な数値を選択することです。

誰かがより良い方法を知っていますか?使用してmap()、多分?


9
多くのアルゴリズムが一部のサブセットを過大評価するため、リストアイテムが一意であるかどうかは非常に重要な考慮事項であることに注意してください(例: 'abccc'-> [''、 'a'、 'b'、 'c'、 'c') 、 'c'、 'ac'、 'ac'、 'ac'、...]。簡単な回避策は、順列を取得するに、セット内のすべての要素を押し出すことです
ninjagecko

@ninjagecko Setライブラリの使用は、それぞれが最高でO(n)であるため効率的ではありません。したがって、n個の関数をセットに追加することは、実際にはO(n ^ 2)です。
Scott Biggs

質問を注意深く読んだところ、OPは、すべての組み合わせではなく、15の数字のリストのPowerSetを求めているようです。これが答えが至る所にある理由だと思います。
スコットビッグス

@Scott Biggs:ここでPythonについて理解していることを確認しますか?セットの挿入と検索はO(1)の平均的なケースです。彼らは辞書のようなものです。彼らはハッシュを使用します。Pythonには特別なセットライブラリはありません(標準ライブラリにあります)。ここでは関数ではなく数字を挿入しています。(それでもO(2 ^ n)メモリを使用するのは非効率的です。パワーセットではなく組み合わせが必要な人にとっての適切な解決策は、単純な再帰的な実装productなどです)
ninjagecko

回答:


467

itertools.combinationsを見てください

itertools.combinations(iterable, r)

入力イテラブルから、要素の長さrのサブシーケンスを返します。

組み合わせは辞書式ソート順で出力されます。したがって、入力イテラブルがソートされている場合、組み合わせタプルはソートされた順序で生成されます。

2.6以降、電池が付属!


31
あなたはそれをすべてリストすることができます。list(itertools.combinations(iterable, r))
silgon

1
を必要としないものはありますかr、つまり、要素の任意の長さのサブシーケンスの組み合わせ。
mLstudent33

630

この答えは1つの側面を逃しました。OPは長さ「r」の組み合わせだけでなく、すべての組み合わせを要求しました。

したがって、すべての長さ "L"をループする必要があります。

import itertools

stuff = [1, 2, 3]
for L in range(0, len(stuff)+1):
    for subset in itertools.combinations(stuff, L):
        print(subset)

または-おしゃれにしたい場合(または、あなたの後にコードを読む人の頭を曲げたい場合)は、 "combinations()"ジェネレーターのチェーンを生成し、それを反復できます。

from itertools import chain, combinations
def all_subsets(ss):
    return chain(*map(lambda x: combinations(ss, x), range(0, len(ss)+1)))

for subset in all_subsets(stuff):
    print(subset)

42
ご支援ありがとうございます!上記の返信を投稿してから数週間で、Benが求めている概念の名前は、15アイテムの元のセットの「パワーセット」であることがわかりました。実際、サンプルの実装は、標準のpython「itertools」ドキュメントページにあります:docs.python.org/library/itertools.html(「powerset」のgrep)。
Dan H

38
ここまで読んだ人のために:ドキュメントのpowerset()レシピセクションにあるジェネレーター関数はシンプルで、メモリ使用量が少ない可能性があり、ここに示す実装よりも高速である可能性があります。itertools
martineau

辞書式順にすべての組み合わせを生成することは可能ですか?
guik

@guik:itertools.combinations生成されたリストでアイテムの順序が保持されることを99%確信しています。したがって、入力が字句的にソートされている場合、各出力も同様にソートされます。
Dan H

はい、itertools.combinationsnの中のkの組み合わせを辞書式順序で生成しますが、nの中のk までのすべての組み合わせではありません。k までのpowersetすべての組み合わせを生成しますが、私が理解している限り、辞書式順序ではありません:powerset([1,2])-> [()、(1、)、(2、)、(1、2)] 。[()、(1、)、(1、2)、(2、)]にすべきではありませんか?
guik

52

これも怠惰なワンライナーであり、同じくitertoolsを使用しています:

from itertools import compress, product

def combinations(items):
    return ( set(compress(items,mask)) for mask in product(*[[0,1]]*len(items)) )
    # alternative:                      ...in product([0,1], repeat=len(items)) )

この答えの背後にある主なアイデア:2 ^ Nの組み合わせがあります-長さNのバイナリ文字列の数と同じです。各バイナリ文字列について、 "1"に対応するすべての要素を選択します。

items=abc * mask=###
 |
 V
000 -> 
001 ->   c
010 ->  b
011 ->  bc
100 -> a
101 -> a c
110 -> ab
111 -> abc

考慮すべき事項:

  • これは、あなたが呼び出すことができることが必要len(...)items(回避策:場合はitems発電機のような反復可能なようなものである、との最初のリストにそれを回しますitems=list(_itemsArg)
  • これには、反復の順序がitemsランダムでないことが必要です(回避策:狂気にしないでください)
  • これは、アイテムがユニークな、または他のあることが必要{2,2,1}{2,1,1}するだろう崩壊の両方{2,1}(回避策:使用collections.Counterドロップインの代替としてset、後で使用する必要があるかもしれませんが、それは...基本的に多重集合だtuple(sorted(Counter(...).elements()))あなたはそれがハッシュ可能である必要があれば)

デモ

>>> list(combinations(range(4)))
[set(), {3}, {2}, {2, 3}, {1}, {1, 3}, {1, 2}, {1, 2, 3}, {0}, {0, 3}, {0, 2}, {0, 2, 3}, {0, 1}, {0, 1, 3}, {0, 1, 2}, {0, 1, 2, 3}]

>>> list(combinations('abcd'))
[set(), {'d'}, {'c'}, {'c', 'd'}, {'b'}, {'b', 'd'}, {'c', 'b'}, {'c', 'b', 'd'}, {'a'}, {'a', 'd'}, {'a', 'c'}, {'a', 'c', 'd'}, {'a', 'b'}, {'a', 'b', 'd'}, {'a', 'c', 'b'}, {'a', 'c', 'b', 'd'}]

46

@Dan Hによる非常に支持された回答の下のコメントではpowerset()itertoolsドキュメントでのレシピについて言及されていますDan自身によるものを含む)。ただし、これまでのところ、回答として誰も投稿していません。それはおそらく、問題への最善のアプローチではないにしても、より優れたアプローチの1つであり、別のコメンターから少し励まされているため、以下に示します。この関数は、可能な限りすべての長さのリスト要素のすべての一意の組み合わせ(ゼロとすべての要素を含むものを含む)を生成します。

:微妙に異なる目的が一意の要素の組み合わせのみを取得することである場合は、行s = list(iterable)s = list(set(iterable))に変更して、重複する要素を排除します。とにかく、iterableが最終的にlist手段に変換されるという事実は、(他のいくつかの回答とは異なり)ジェネレーターで機能することを意味します。

from itertools import chain, combinations

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)  # allows duplicate elements
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

stuff = [1, 2, 3]
for i, combo in enumerate(powerset(stuff), 1):
    print('combo #{}: {}'.format(i, combo))

出力:

combo #1: ()
combo #2: (1,)
combo #3: (2,)
combo #4: (3,)
combo #5: (1, 2)
combo #6: (1, 3)
combo #7: (2, 3)
combo #8: (1, 2, 3)

何がlist()最初の場所での変換は?
AMC

@Alexander:イテラブルの長さを決定できるようにするため。
martineau

36

これは再帰を使用するものです:

>>> import copy
>>> def combinations(target,data):
...     for i in range(len(data)):
...         new_target = copy.copy(target)
...         new_data = copy.copy(data)
...         new_target.append(data[i])
...         new_data = data[i+1:]
...         print new_target
...         combinations(new_target,
...                      new_data)
...                      
... 
>>> target = []
>>> data = ['a','b','c','d']
>>> 
>>> combinations(target,data)
['a']
['a', 'b']
['a', 'b', 'c']
['a', 'b', 'c', 'd']
['a', 'b', 'd']
['a', 'c']
['a', 'c', 'd']
['a', 'd']
['b']
['b', 'c']
['b', 'c', 'd']
['b', 'd']
['c']
['c', 'd']
['d']

これを変更して、印刷する代わりにリストのリストを返すことができますか?
James Vickery 2017年

@JamesVickeryはい、関数の外でリストを作成し、それに追加するか、(より良い)関数をジェネレーターにするか、 'yield'キーワードを見てください:)
Dangercrow

new_data = copy.copy(data)-この行は私が見る限り冗長です、それは何にも影響を与えません
Dmitriy Fialkovskiy

31

このワンライナーは、すべての組み合わせ(元のリスト/セットに異なる要素が含まれている場合は0n項目の間n)を提供し、ネイティブメソッドを使用しますitertools.combinations

Python 2

from itertools import combinations

input = ['a', 'b', 'c', 'd']

output = sum([map(list, combinations(input, i)) for i in range(len(input) + 1)], [])

Python 3

from itertools import combinations

input = ['a', 'b', 'c', 'd']

output = sum([list(map(list, combinations(input, i))) for i in range(len(input) + 1)], [])

出力は次のようになります。

[[],
 ['a'],
 ['b'],
 ['c'],
 ['d'],
 ['a', 'b'],
 ['a', 'c'],
 ['a', 'd'],
 ['b', 'c'],
 ['b', 'd'],
 ['c', 'd'],
 ['a', 'b', 'c'],
 ['a', 'b', 'd'],
 ['a', 'c', 'd'],
 ['b', 'c', 'd'],
 ['a', 'b', 'c', 'd']]

オンラインでお試しください:

http://ideone.com/COghfX


これは順列です
AdHominem

15
@AdHominem:いいえ、違います。すべての組み合わせのリストです。順列には、たとえばが含まれます['b', 'a']
naught101

TypeError: can only concatenate list (not "map") to list
0x48piraj

@ 0x48piraj:通知していただきありがとうございます。結果的に回答を編集しました!
Mathieu Rodic

21

私は、ベンが実際にすべての組み合わせを求めたダンHに同意します。itertools.combinations()すべての組み合わせが得られるわけではありません。

もう1つの問題は、反復可能な入力が大きい場合、リスト内のすべてではなくジェネレータを返すほうがよいでしょう。

iterable = range(10)
for s in xrange(len(iterable)+1):
  for comb in itertools.combinations(iterable, s):
    yield comb

1
いい例です。私はジェネレーターが好きです...そして私はそれらを持っていることでPythonが大好きです!この例では、一度に1つの組み合わせ()オブジェクトのみがあり、一度に1つの組み合わせが生成されます。(おそらく、使用例として、この周りにdefブロックを追加する必要があります。)私の実装(上記のchain()を使用)はそれほど悪くないことに注意してください。すべてのlen(iterable)ジェネレータが一度...しかし、それは2つのlen(iterable)の組み合わせすべてを一度に作成するわけではありません。
Dan H

18

これは、再帰をサポートするすべてのプログラミング言語に簡単に転送できるアプローチです(イターツールなし、生成なし、リスト内包なし)

def combs(a):
    if len(a) == 0:
        return [[]]
    cs = []
    for c in combs(a[1:]):
        cs += [c, c+[a[0]]]
    return cs

>>> combs([1,2,3,4,5])
[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], ..., [5, 4, 3, 2, 1]]

ああ!素晴らしい実装です。PrologのHEAD = a [0]、TAIL = a [1:]を認識します。または、Lispのcar = a [0]、cdr = a [1:]。ここでメモを使えるかしら…
ハビエル・ルイス

そうだね。リストのスライスはO(k)で、kはスライスの長さです。最初の実行以外のすべての実行でO(1)になるマップでルックアップを行うことで、これを高速化できると思います。ただし、この実装はパフォーマンスのために参照しないでください。そのためにより良い実装が存在します。この実装は、単純化と他のほとんどの言語への移植性のためだけです。
ジョナサンR

14

この単純なコードを使用して、Pythonでリストのすべての組み合わせを生成できます

import itertools

a = [1,2,3,4]
for i in xrange(0,len(a)+1):
   print list(itertools.combinations(a,i))

結果は次のようになります:

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

このコードのバグ:空のセットを返しません。xrange(0、...)を意味する可能性がありますが、テストされていません。edit:私は先に進み、それを修正するためにあなたの答えを編集しました。
ninjagecko 2015

13

itertoolsやその他の追加のライブラリをインポートせずに回答を求める人のためにこの関数を追加すると思いました。

def powerSet(items):
    """
    Power set generator: get all possible combinations of a list’s elements

    Input:
        items is a list
    Output:
        returns 2**n combination lists one at a time using a generator 

    Reference: edx.org 6.00.2x Lecture 2 - Decision Trees and dynamic programming
    """

    N = len(items)
    # enumerate the 2**N possible combinations
    for i in range(2**N):
        combo = []
        for j in range(N):
            # test bit jth of integer i
            if (i >> j) % 2 == 1:
                combo.append(items[j])
        yield combo

簡単な利回りジェネレーターの使用:

for i in powerSet([1,2,3,4]):
    print (i, ", ",  end="")

上記の使用例の出力:

[]、[1]、[2]、[1、2]、[3]、[1、3]、[2、3]、[1、2、3]、[4]、[1、4] 、[2、4]、[1、2、4]、[3、4]、[1、3、4]、[2、3、4]、[1、2、3、4]、


これは非常にきちんとした解決策だと思います。
greentec

8

次に、itertools.combinations関数の使用を含むさらに別のソリューション(ワンライナー)を示しますが、ここでは(forループや合計ではなく)二重リスト内包表記を使用しています。

def combs(x):
    return [c for i in range(len(x)+1) for c in combinations(x,i)]

デモ:

>>> combs([1,2,3,4])
[(), 
 (1,), (2,), (3,), (4,), 
 (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), 
 (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), 
 (1, 2, 3, 4)]

5
from itertools import permutations, combinations


features = ['A', 'B', 'C']
tmp = []
for i in range(len(features)):
    oc = combinations(features, i + 1)
    for c in oc:
        tmp.append(list(c))

出力

[
 ['A'],
 ['B'],
 ['C'],
 ['A', 'B'],
 ['A', 'C'],
 ['B', 'C'],
 ['A', 'B', 'C']
]

4

以下は、他の同様の回答https://stackoverflow.com/a/23743696/711085と同様の「標準の再帰的回答」です。(すべてのN!順列を処理する方法がないため、スタックスペースが不足することを心配する必要はありません。)

それは順番にすべての要素を訪問し、それを取るか、または去ります(このアルゴリズムから2 ^ Nのカーディナリティを直接見ることができます)。

def combs(xs, i=0):
    if i==len(xs):
        yield ()
        return
    for c in combs(xs,i+1):
        yield c
        yield c+(xs[i],)

デモ:

>>> list( combs(range(5)) )
[(), (0,), (1,), (1, 0), (2,), (2, 0), (2, 1), (2, 1, 0), (3,), (3, 0), (3, 1), (3, 1, 0), (3, 2), (3, 2, 0), (3, 2, 1), (3, 2, 1, 0), (4,), (4, 0), (4, 1), (4, 1, 0), (4, 2), (4, 2, 0), (4, 2, 1), (4, 2, 1, 0), (4, 3), (4, 3, 0), (4, 3, 1), (4, 3, 1, 0), (4, 3, 2), (4, 3, 2, 0), (4, 3, 2, 1), (4, 3, 2, 1, 0)]

>>> list(sorted( combs(range(5)), key=len))
[(), 
 (0,), (1,), (2,), (3,), (4,), 
 (1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (4, 3), 
 (2, 1, 0), (3, 1, 0), (3, 2, 0), (3, 2, 1), (4, 1, 0), (4, 2, 0), (4, 2, 1), (4, 3, 0), (4, 3, 1), (4, 3, 2), 
 (3, 2, 1, 0), (4, 2, 1, 0), (4, 3, 1, 0), (4, 3, 2, 0), (4, 3, 2, 1), 
 (4, 3, 2, 1, 0)]

>>> len(set(combs(range(5))))
32

2

リスト内包表記の使用:

def selfCombine( list2Combine, length ):
    listCombined = str( ['list2Combine[i' + str( i ) + ']' for i in range( length )] ).replace( "'", '' ) \
                     + 'for i0 in range(len( list2Combine ) )'
    if length > 1:
        listCombined += str( [' for i' + str( i ) + ' in range( i' + str( i - 1 ) + ', len( list2Combine ) )' for i in range( 1, length )] )\
            .replace( "', '", ' ' )\
            .replace( "['", '' )\
            .replace( "']", '' )

    listCombined = '[' + listCombined + ']'
    listCombined = eval( listCombined )

    return listCombined

list2Combine = ['A', 'B', 'C']
listCombined = selfCombine( list2Combine, 2 )

出力は次のようになります:

['A', 'A']
['A', 'B']
['A', 'C']
['B', 'B']
['B', 'C']
['C', 'C']

4
この提案は、文字列のマングリングを行ってセットを構築することです?!?!聖なるカラス....そして:パワーセットを返すのではなく、combinations_with_replacement()のようなものです。(docs.python.org/library/…を参照)
Dan H

これは実際にCombination_with_replacement ()と同じですが、少なくとも私のボックスでは、itertoolsよりもわずかに速く実行されます。何と言えば、私はリスト内包表記が好きです。
zmk

1
答えてくれてありがとう!['A'、 'A']、['A'、 'B']、['A'、 'C​​']、['B'、 'A']、[ 'B'、 'B']、['B'、 'C​​']、['C'、 'A']、['C'、 'B']および['C'、 'C​​']すべて?
Karyo

非常に興味深いですが、私のpythonはここで微妙なところを理解するのが難しいです。異なるスコープでlistCombinedを使用することについて特別なことはありますか?forループがすべて1行にあるという事実はありますか?私はこれを少しの運でJavaに移植しようとしています。
Scott Biggs

2

このコードは、ネストされたリストを使用した単純なアルゴリズムを採用しています...

# FUNCTION getCombos: To generate all combos of an input list, consider the following sets of nested lists...
#
#           [ [ [] ] ]
#           [ [ [] ], [ [A] ] ]
#           [ [ [] ], [ [A],[B] ],         [ [A,B] ] ]
#           [ [ [] ], [ [A],[B],[C] ],     [ [A,B],[A,C],[B,C] ],                   [ [A,B,C] ] ]
#           [ [ [] ], [ [A],[B],[C],[D] ], [ [A,B],[A,C],[B,C],[A,D],[B,D],[C,D] ], [ [A,B,C],[A,B,D],[A,C,D],[B,C,D] ], [ [A,B,C,D] ] ]
#
#  There is a set of lists for each number of items that will occur in a combo (including an empty set).
#  For each additional item, begin at the back of the list by adding an empty list, then taking the set of
#  lists in the previous column (e.g., in the last list, for sets of 3 items you take the existing set of
#  3-item lists and append to it additional lists created by appending the item (4) to the lists in the
#  next smallest item count set. In this case, for the three sets of 2-items in the previous list. Repeat
#  for each set of lists back to the initial list containing just the empty list.
#

def getCombos(listIn = ['A','B','C','D','E','F'] ):
    listCombos = [ [ [] ] ]     # list of lists of combos, seeded with a list containing only the empty list
    listSimple = []             # list to contain the final returned list of items (e.g., characters)

    for item in listIn:
        listCombos.append([])   # append an emtpy list to the end for each new item added
        for index in xrange(len(listCombos)-1, 0, -1):  # set the index range to work through the list
            for listPrev in listCombos[index-1]:        # retrieve the lists from the previous column
                listCur = listPrev[:]                   # create a new temporary list object to update
                listCur.append(item)                    # add the item to the previous list to make it current
                listCombos[index].append(listCur)       # list length and append it to the current list

                itemCombo = ''                          # Create a str to concatenate list items into a str
                for item in listCur:                    # concatenate the members of the lists to create
                    itemCombo += item                   # create a string of items
                listSimple.append(itemCombo)            # add to the final output list

    return [listSimple, listCombos]
# END getCombos()

したがって、このコードが行うように見えるのは、[listOfCombinations、listOfCombinationsGroupedBySize]を返すことです。残念ながら、デモ入力で実行すると、64要素ではなく63要素になります。空のセット(この場合は空の文字列"")が欠落しているようです。
ninjagecko 2015

2

itertoolsを使用してすべての組み合わせを取得する方がはるかに実用的であることはわかっています、多くのコードを作成たい場合は、リスト内包だけでこれ実現することもできます。

2つのペアの組み合わせの場合:

    lambda l: [(a, b) for i, a in enumerate(l) for b in l[i+1:]]


そして、3つのペアの組み合わせの場合、これは次のように簡単です。

    lambda l: [(a, b, c) for i, a in enumerate(l) for ii, b in enumerate(l[i+1:]) for c in l[i+ii+2:]]


結果はitertools.combinationsを使用した場合と同じです。

import itertools
combs_3 = lambda l: [
    (a, b, c) for i, a in enumerate(l) 
    for ii, b in enumerate(l[i+1:]) 
    for c in l[i+ii+2:]
]
data = ((1, 2), 5, "a", None)
print("A:", list(itertools.combinations(data, 3)))
print("B:", combs_3(data))
# A: [((1, 2), 5, 'a'), ((1, 2), 5, None), ((1, 2), 'a', None), (5, 'a', None)]
# B: [((1, 2), 5, 'a'), ((1, 2), 5, None), ((1, 2), 'a', None), (5, 'a', None)]

2

itertoolsを使用しない場合:

def combine(inp):
    return combine_helper(inp, [], [])


def combine_helper(inp, temp, ans):
    for i in range(len(inp)):
        current = inp[i]
        remaining = inp[i + 1:]
        temp.append(current)
        ans.append(tuple(temp))
        combine_helper(remaining, temp, ans)
        temp.pop()
    return ans


print(combine(['a', 'b', 'c', 'd']))

2

ここに2つの実装があります itertools.combinations

リストを返すもの

def combinations(lst, depth, start=0, items=[]):
    if depth <= 0:
        return [items]
    out = []
    for i in range(start, len(lst)):
        out += combinations(lst, depth - 1, i + 1, items + [lst[i]])
    return out

ジェネレーターを返す

def combinations(lst, depth, start=0, prepend=[]):
    if depth <= 0:
        yield prepend
    else:
        for i in range(start, len(lst)):
            for c in combinations(lst, depth - 1, i + 1, prepend + [lst[i]]):
                yield c

prepend引数は静的であり、呼び出しのたびに変更されるわけではないため、それらにヘルパー関数を提供することをお勧めします。

print([c for c in combinations([1, 2, 3, 4], 3)])
# [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]

# get a hold of prepend
prepend = [c for c in combinations([], -1)][0]
prepend.append(None)

print([c for c in combinations([1, 2, 3, 4], 3)])
# [[None, 1, 2, 3], [None, 1, 2, 4], [None, 1, 3, 4], [None, 2, 3, 4]]

これは非常に表面的なケースですが、申し訳ありませんが安全です。


2

これはどうですか..リストの代わりに文字列を使用しましたが、同じことです。文字列はPythonではリストのように処理できます。

def comb(s, res):
    if not s: return
    res.add(s)
    for i in range(0, len(s)):
        t = s[0:i] + s[i + 1:]
        comb(t, res)

res = set()
comb('game', res) 

print(res)

2

itertoolsからの組み合わせ

import itertools
col_names = ["aa","bb", "cc", "dd"]
all_combinations = itertools.chain(*[itertools.combinations(col_names,i+1) for i,_ in enumerate(col_names)])
print(list(all_combinations))

ありがとう


2

itertoolsPython 3がなければ、次のようなことができます:

def combinations(arr, carry):
    for i in range(len(arr)):
        yield carry + arr[i]
        yield from combinations(arr[i + 1:], carry + arr[i])

最初はどこ carry = "".


2

3つの機能:

  1. n要素リストのすべての組み合わせ
  2. 順序が明確でないn個の要素リストのすべての組み合わせ
  3. すべての順列
import sys

def permutations(a):
    return combinations(a, len(a))

def combinations(a, n):
    if n == 1:
        for x in a:
            yield [x]
    else:
        for i in range(len(a)):
            for x in combinations(a[:i] + a[i+1:], n-1):
                yield [a[i]] + x

def combinationsNoOrder(a, n):
    if n == 1:
        for x in a:
            yield [x]
    else:
        for i in range(len(a)):
            for x in combinationsNoOrder(a[:i], n-1):
                yield [a[i]] + x

if __name__ == "__main__":
    for s in combinations(list(map(int, sys.argv[2:])), int(sys.argv[1])):
        print(s)

私はこれがとても好きです!!! ありがとうございました!!!Pythonの組み合わせ関数は少し奇妙ですが。数学では、「combinations」関数はバリエーションであり、「combinationsNoOrder」は実際には組み合わせです。今回は数学のように、数学の分野からパイソンに来た人を混乱させるのではないでしょうか。とにかく、素晴らしい解決策です、多くの利益に感謝します!
Đumićブラニスラフ

1

これは私の実装です

    def get_combinations(list_of_things):
    """gets every combination of things in a list returned as a list of lists

    Should be read : add all combinations of a certain size to the end of a list for every possible size in the
    the list_of_things.

    """
    list_of_combinations = [list(combinations_of_a_certain_size)
                            for possible_size_of_combinations in range(1,  len(list_of_things))
                            for combinations_of_a_certain_size in itertools.combinations(list_of_things,
                                                                                         possible_size_of_combinations)]
    return list_of_combinations

1
ここに掲載されている以前の実装よりもうまく解決している実装は何ですか。
user1767754

0

優れたパワーセット機能も使えますmore_itertoolsパッケージます。

from more_itertools import powerset

l = [1,2,3]
list(powerset(l))

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

OPの要件を満たしていることも確認できます

from more_itertools import ilen

assert ilen(powerset(range(15))) == 32_768

-1
def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD
# combinations(range(4), 3) --> 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
    return
indices = range(r)
yield tuple(pool[i] for i in indices)
while True:
    for i in reversed(range(r)):
        if indices[i] != i + n - r:
            break
    else:
        return
    indices[i] += 1
    for j in range(i+1, r):
        indices[j] = indices[j-1] + 1
    yield tuple(pool[i] for i in indices)


x = [2, 3, 4, 5, 1, 6, 4, 7, 8, 3, 9]
for i in combinations(x, 2):
    print i

1
私が正しい場合、これはpythonのドキュメント[ docs.python.org/3.6/library/itertools.html ] からコピーされた正確なコードです。もしそうなら、ソースを参照してください。
GabrielChu

興味深いアプローチ
ペロ

-1

私のように誰かが逆のリストを探しているなら:

stuff = [1, 2, 3, 4]

def reverse(bla, y):
    for subset in itertools.combinations(bla, len(bla)-y):
        print list(subset)
    if y != len(bla):
        y += 1
        reverse(bla, y)

reverse(stuff, 1)

-1
flag = 0
requiredCals =12
from itertools import chain, combinations

def powerset(iterable):
    s = list(iterable)  # allows duplicate elements
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

stuff = [2,9,5,1,6]
for i, combo in enumerate(powerset(stuff), 1):
    if(len(combo)>0):
        #print(combo , sum(combo))
        if(sum(combo)== requiredCals):
            flag = 1
            break
if(flag==1):
    print('True')
else:
    print('else')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.