web-dev-qa-db-ja.com

Pythonでサイズk(k個の要素を含む)のすべてのサブセットを生成します

値のセットがあり、2つの要素を含むすべてのサブセットのリストを作成したいと思います。

たとえば、ソースセット([1,2,3])には、次の2要素のサブセットがあります。

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

Pythonでこれを行う方法はありますか?

14
John Manak

あなたが望むようです itertools.combinations

>>> list(itertools.combinations((1, 2, 3), 2))
[(1, 2), (1, 3), (2, 3)]

セットが必要な場合は、明示的に変換する必要があります。リストの代わりに反復可能を気にせず、Python 3を使用している場合は、mapを使用できます:

>>> s = set((1, 2, 3))
>>> map(set, itertools.combinations(s, 2))
<map object at 0x10cdc26d8>

すべての結果を一度に表示するには、mapの出力をlistに渡すことができます。 (Python 2では、mapの出力は自動的にリストになります。)

>>> list(map(set, itertools.combinations(s, 2)))
[{1, 2}, {1, 3}, {2, 3}]

ただし、リストが必要であることがわかっている場合は、リストの理解がわずかに向上します(h/t Jacob Bowyer ):

>>> [set(i) for i in itertools.combinations(s, 2)]
[{1, 2}, {1, 3}, {2, 3}]
27
senderle

これは、すべての2要素セットを含む{1, 2, 3}(または任意のセット)の べき集合 のサブセットです。

Python itertoolsドキュメント を参照し、「べき集合」という用語でこの問題の一般的な答えを検索してください。

2
Alex Reynolds

別の見方をするために、私は_{1.....N}_のサイズ2のすべてのサブセットを反復する方法を探したので、_itertools.combinations_をテストしました。

_import itertools
from time import time


N = 7000
lst = [i for i in xrange(N)]

st = time()
c1 = 0
for x in itertools.combinations(lst, 2):
    c1 += 1
print "combinations: %f" % (time()-st)

st = time()
c2=0
for x in xrange(N):
    for y in xrange(x):
        c2 += 1
print "double loop: %f" % (time()-st)
print "c1=%d,c2=%d" % (c1,c2)

# prints:
#combinations: 4.247000
#double loop: 3.479000
# c1=24496500,c2=24496500
_

したがって、常に一般的な解決策になるとは限らないと思います。必要なサブセットのサイズが事前にわかっている場合は、forループを使用して反復する方が効率的です。

また、この移動によりリストが作成されるため、list(itertools.combinations(lst, 2))を反復処理しないでください(ジェネレーター自体を使用するよりもはるかに低速です)。

1
omerbp