2016-09-17 20 views
1

は私が見えるPythonのリストを持っていると仮定します。値の順序は関係ありませんので1,2は2,1と同じです。また、それぞれの組み合わせにはない値を含む別のリストを返すこともしたいと思います。例:上記のためPythonの組み合わせ

Combination 1,2/Remainder 3,4 
Combination 2,3/Remainder 1,4 
Combination 1,2,3/Remainder 4 
Combination 1,2,3,4/ Remainder - 

返されたリストは、私が最初の部分は、おそらく達成することができることを実現する、私はほんの数例を示してきました

combination = [[1,2], [2,3], [1,2,3], [1,2,3,4]] 
remainder = [[3,4], [1,4], [4], []] 

...

だろうitertools.combinationsを使用していますが、ループなしで組み合わせで使用されていない値を返すにはどうすればよいですか?

答えて

2

ビルが、その代わりに、バイナリへの一定の範囲内の数字を変換する、あなただけのすべての組み合わせを取得するためにitertools.productを使用することができます10(またはTrueFalse)を使用して、それを「ins」と「outs」をフィルタリングするためのマスクとして使用します。

>>> mask = lambda lst, p, v: [lst[i] for i, e in enumerate(p) if e == v] 
>>> [(mask(lst, p, 1), mask(lst, p, 0)) for p in product([1,0], repeat=len(lst))] 
[([1, 2, 3], []), 
([1, 2], [3]), 
([1, 3], [2]), 
([1], [2, 3]), 
([2, 3], [1]), 
([2], [1, 3]), 
([3], [1, 2]), 
([], [1, 2, 3])] 

あなただけのことができ、リストの「中」の2以上を組み合わせたい場合は:あなたはまた、そのenumerate理解のための関数を定義し、一度に両方の部分を行うことができます

>>> lst = [1,2,3] 
>>> products = list(product([1,0], repeat=len(lst))) 
>>> [[lst[i] for i, e in enumerate(p) if e] for p in products] 
[[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []] 
>>> [[lst[i] for i, e in enumerate(p) if not e] for p in products] 
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]] 

条件を追加:

>>> [(mask(lst, p, 1), mask(lst, p, 0)) for p in product([1,0],repeat=len(lst)) if sum(p) >= 2] 

またはnumpy配列を使用してnumpyの先進的なインデックスを使用します

>>> arr = np.array([1,2,3]) 
>>> [(arr[p==1], arr[p==0]) for p in map(np.array, product([1,0], repeat=len(arr)))] 
[(array([1, 2, 3]), array([])), 
(array([1, 2]), array([3])), 
(array([1, 3]), array([2])), 
(array([1]), array([2, 3])), 
(array([2, 3]), array([1])), 
(array([2]), array([1, 3])), 
(array([3]), array([1, 2])), 
(array([]), array([1, 2, 3]))] 
+0

本当に素敵な実装!!! –

+0

私はこの解決策が大好きです!夢のように働く!ありがとうございました – Mark

2

あなたは差集合を取ることができます。

l = set([1, 2, 3, 4]) 

for i in range(len(l)+1): 
    for comb in itertools.combinations(l, i): 
     print(comb, l.difference(comb)) 

() {1, 2, 3, 4} 
(1,) {2, 3, 4} 
(2,) {1, 3, 4} 
(3,) {1, 2, 4} 
(4,) {1, 2, 3} 
(1, 2) {3, 4} 
(1, 3) {2, 4} 
(1, 4) {2, 3} 
(2, 3) {1, 4} 
(2, 4) {1, 3} 
(3, 4) {1, 2} 
(1, 2, 3) {4} 
(1, 2, 4) {3} 
(1, 3, 4) {2} 
(2, 3, 4) {1} 
(1, 2, 3, 4) set() 
+0

セットの違いは、リストに重複が含まれていない場合にのみ機能することに注意してください。 –

1

はあなたが3である3-1^2に0からの数字のすべてを生成することができ、このベクトル[1 6 3]

を持っていると仮定len([1 6 3])

0 
1 
2 
3 
4 
5 
6 
7 

あなたはバイナリにこの数字を変換することができた後:

0 0 0 
0 0 1 
0 1 0 
0 1 1 
1 0 0 
1 0 1 
1 1 0 
1 1 1 
01組み合わせて1Sの同じ位置での位置にある1その残りの部分である数を追加

[1 6 3] 
0 0 0 
0 0 1 
0 1 0 
0 1 1 
1 0 0 
1 0 1 
1 1 0 
1 1 1 

ライン毎:

は、生成されたシーケンスの一番上にベクトルを入れ0。

ので、例えば、第四行を見て:

Combination: [6,3] 
Remainder: [1] 

終わり:ここ

Combination: [],[3],[6],[6,3],[1],[1,3],[1,6],[1,6,3] 
Remainder: [1,6,3],[1,3],[1],[6,3],[6],[3],[] 

コード:

vec=[1,3,6] 
binary_vec = [format(i,'b').zfill(len(vec)) for i in range(2**len(vec))] 
print([[vec[i] for i,y in enumerate(x) if y != "0"] for x in binary_vec]) 
print([[vec[i] for i,y in enumerate(x) if y == "0"] for x in binary_vec]) 

出力:

enter image description hereこの記事では私の答えでも

ルック:Nunzioによって考えに

Determine list of all possible products from a list of integers in Python

+0

興味深いアプローチ。あなたはまたそれのためのいくつかのコードを提供できますか?また、バイナリに変換する代わりに 'itertools.product([True、False]、repeat = 3)'を使うこともできます。 –

+0

@tobias_kありがとう!私はこの関数を知らなかった:itertools.product([True、False]、repeat = 3)!私もコードを提供しました。 –