2015-10-14 33 views
5

quindi ho una lista di liste di stringhePython tutte le combinazioni di una lista di liste

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

e voglio ottenere tutte le combinazioni possibili, in modo che il risultato è

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

Finora sono venuto su con questo frammento di codice

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 

in gran parte a seguito di una risposta in this post.

Ma che si traduce in

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

e attualmente sto perplesso, cercando di trovare un elegante modo divinatorio per decomprimere quei tuple.

risposta

6

È possibile utilizzare itertools.chain.from_iterable per appiattire la tupla di elenchi in un elenco. Esempio -

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

Bello. Sono spesso meravigliato di quanto siano potenti gli itertools. –

+0

Perfetto. Esattamente quello che stavo cercando. Grazie! –

0

Un'idea per un tale obiettivo è quello di mappare gli interi da [0..2**n-1] dove n è il numero di sottoliste a tutti i vostri elemento di destinazione in base a una molto semplice regola: Prendere l'elemento di indice k se (2**k)&i!=0 dove corro su [0..2**n-1]. In altre parole, i deve essere letto a bit e, per ogni bit impostato, viene mantenuto l'elemento corrispondente da l. Da un punto di vista matematico è uno dei modi più puliti per ottenere ciò che si vuole fare poiché segue molto da vicino la definizione delle parti di un set (dove si hanno esattamente 2**n parti per un set con n elementi).

non provato ma qualcosa di simile che dovrebbe funzionare:

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) 

Se non si desidera che l'elenco vuoto, basta sostituire la relativa riga con:

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

Se volete tutte le combinazioni, si può considerare questo semplice modo:

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

Se la lista originale conteneva 4 liste, questo non conterrebbe comunque le combinazioni risultanti di lunghezza 3. –

+0

@Matt M. Sì, hai ragione, non ho considerato che la lista contenga 4 liste, mostri solo un caso semplice. in caso di più di 3 liste, il metodo di Anand S Kumar sarà quello che ti serve. Grazie per avermi fatto sapere. –

0

Con le liste di comprensione:

combs=[sum(x,[]) for i in range(len(l)) for x in itertools.combinations(l,i+1)] 
Problemi correlati