2015-10-14 36 views
5

Więc mam listę list ciągówPython wszystkie kombinacje listy list

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

i chcę uzyskać wszystkie możliwe kombinacje, takie, że wynik jest

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

tej pory I mają pochodzić z tego fragmentu kodu

input = [['a','b'],['c','d'],['e','f']] 
combs = [] 
for i in xrange(1, len(input)+1): 
    els = [x for x in itertools.combinations(input, i)] 
    combs.extend(els) 
print combs 

dużej mierze następującej odpowiedzi w this post.

Ale to skutkuje

[(['a','b'],),(['c','d'],),(['e','f'],), 
(['a','b'],['c','d']),(['a','b'],['e','f']),(['c','d'],['e','f']), 
(['a','b'],['c', 'd'],['e', 'f'])] 

i jestem obecnie zakłopotany, próbując znaleźć elegancką, pythonic sposób rozpakować te krotki.

Odpowiedz

6

Możesz użyć itertools.chain.from_iterable, aby spłaszczyć krotkę list do listy. Przykład -

import itertools 
input = [['a','b'],['c','d'],['e','f']] 
combs = [] 
for i in xrange(1, len(input)+1): 
    els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)] 
    combs.extend(els) 

Demo -

>>> import itertools 
>>> input = [['a','b'],['c','d'],['e','f']] 
>>> combs = [] 
>>> for i in range(1, len(input)+1): 
...  els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)] 
...  combs.extend(els) 
... 
>>> import pprint 
>>> pprint.pprint(combs) 
[['a', 'b'], 
['c', 'd'], 
['e', 'f'], 
['a', 'b', 'c', 'd'], 
['a', 'b', 'e', 'f'], 
['c', 'd', 'e', 'f'], 
['a', 'b', 'c', 'd', 'e', 'f']] 
+1

Nice. Często jestem zaskoczony, jak potężne jest 'itertools'. –

+0

Idealny. Dokładnie to, czego szukałem. Dzięki! –

0

Jeden pomysł na taki cel jest mapowanie liczby całkowite od [0..2**n-1] gdzie n oznacza liczbę podlist do wszystkich elementu docelowego według bardzo prosta rule: Weź element indeksu k, jeśli (2**k)&i!=0, gdzie biegnie ponad [0..2**n-1]. Innymi słowy, i musi być odczytywany bitowo, a dla każdego zestawu bitów zachowany jest odpowiedni element z l. Z matematycznego punktu widzenia jest to jeden z najczystszych sposobów na osiągnięcie tego, co chcesz zrobić, ponieważ bardzo ściśle podąża za definicją części zestawu (gdzie masz dokładnie 2**n części dla zestawu z n elementami).

Nie próbowałem, ale coś takiego powinno działać:

l = [['a','b'],['c','d'],['e','f']]              
n = len(l) 
output = [] 
for i in range(2**n): 
    s = [] 
    for k in range(n): 
     if (2**k)&i: s = s + l[k] 
    output.append(s) 

Jeśli nie chcesz, pustą listę, po prostu zastąpić odpowiednią linię z:

for i in range(1,2**n): 
0

Jeśli chcesz wszystkie kombinacje, można rozważyć to prosty sposób:

import itertools 

a = [['a','b'],['c','d'],['e','f']] 
a = a + [i + j for i in a for j in a if i != j] + [list(itertools.chain.from_iterable(a))] 
+0

Jeśli oryginalna lista zawierała 4 listy, nie zawierałaby jednak wynikowych kombinacji długości 3. –

+0

@Matt M. Tak, masz rację, nie uważałem, że lista zawiera 4 listy, tylko pokazuje prosty przypadek. w przypadku więcej niż 3 list, metoda Anand S Kumar będzie tą, której potrzebujesz. Dziękuję za informację. –

0

Z list ze zrozumieniem:

combs=[sum(x,[]) for i in range(len(l)) for x in itertools.combinations(l,i+1)] 
Powiązane problemy