2011-12-03 20 views
31

Necesito poder hacer una lista que contenga todas las combinaciones posibles de una lista ingresada. Por ejemplo, la lista [1,2,3] debería devolver [1 [1,2] [1,3] 2 [2,3] 3 [1,2,3]] La lista no tiene por qué ser en cualquier orden particular En este sitio he encontrado muchas funciones usando las herramientas de iteración, pero esas son objetos que regresan cuando solo necesito una lista. Soy un principiante en la codificación de pitón por lo que cualquier pensamiento o idea sería muy apreciada.Haciendo todas las combinaciones posibles de una lista en python

Respuesta

40

Simplemente use itertools.combinations. Por ejemplo:

import itertools 

lst = [1, 2, 3] 
combs = [] 

for i in xrange(1, len(lst)+1): 
    combs.append(i) 
    els = [list(x) for x in itertools.combinations(lst, i)] 
    combs.append(els) 

Ahora combs mantiene este valor:

[1, [[1], [2], [3]], 2, [[1, 2], [1, 3], [2, 3]], 3, [[1, 2, 3]]] 

Sí, es un poco diferente de la salida de la muestra que ya ha proporcionado, pero en la que la producción no se enumerando todas las combinaciones posibles.

Estoy enumerando el tamaño de la combinación antes de la lista real para cada tamaño, si lo que necesita son simplemente las combinaciones (sin el tamaño, como aparece en la salida de muestra) entonces pruebe estas otras versiones de el código:

import itertools 

lst = [1, 2, 3] 
combs = [] 

for i in xrange(1, len(lst)+1): 
    els = [list(x) for x in itertools.combinations(lst, i)] 
    combs.extend(els) 

Ahora combs mantiene este valor:

[[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 
+0

Importé el comando itertools usando >>> desde la importación de itertools * Pero mi intérprete me dice que itertools no está definido. Lo siento por todas las preguntas simples, soy muy nuevo en Python y la programación en general. – Charles

+0

esto no es lo que pidió OP. – juliomalegria

+0

@ julio.alegria sí, eso es lo que pidió el OP, acabo de editar mi respuesta –

5

las funciones de los iteradores de retorno del módulo itertools. Todo lo que necesita hacer para convertir esto en listas es llamar al list() sobre el resultado.

Sin embargo, ya que tendrá que llamar al itertools.combinations tres veces por separado (una para cada longitud diferente), puede simplemente usar list.extend para agregar todos los elementos del iterador a su lista final.

intente lo siguiente:

import itertools 
in_list = [1, 2, 3] 
out_list = [] 
for i in range(1, len(in_list)+1): 
    out_list.extend(itertools.combinations(in_list, i)) 

o como una lista de comprensión:

out_list = [c for i in range(len(in_list)) for c in itertools.combinations(in_list, i+1)] 

Estos darán como resultado la siguiente lista:

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

Si desea listas en lugar de tuplas y para convertir las tuplas de longitud única en solo el valor, puede hacer lo siguiente:

out_list = [x[0] if len(x) == 1 else list(x) for x in out_list] 
# [1, 2, 3, [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

O para dejar los elementos individuales como listas:

+0

Intenté usar esto pero el intérprete dijo que podía No uso iter en NoneTypes. – Charles

+0

ambas soluciones siguen devolviendo una lista de tuplas. – juliomalegria

+0

Sí, necesito una lista de listas, no de tuplas. ¿Hay alguna manera de resolver el problema sin usar las itertools? – Charles

5

Se podría solucionar el problema con itertools.combinations dentro de un bucle:

>>> l = [1,2,3] 
>>> comb = [] 
>>> for i in range(len(l)): 
... comb += itertools.combinations(l,i+1) 
... 
>>> comb 
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 

Y si los quieres como una lista :

>>> comb_list = [ list(t) for t in comb ] 
>>> comb_list 
[[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

EDITAR: El primer parámetro de combinaciones es el iterable y el segundo es la longitud de las tuplas resultantes (en este caso, yendo de 1 a a len(l)).

Más acerca de las combinaciones: http://docs.python.org/library/itertools.html#itertools.combinations

6

El módulo itertools de hecho vuelve generadores en lugar de las listas, pero:

  • generadores son a menudo más eficiente que las listas (especialmente si está generando un gran número de combinaciones)
  • Siempre puede convertir generadores a listas usando list(...) cuando realmente lo necesite.

Los chain y combinations funciones de itertools así el trabajo, pero es necesario utilizar Python 2.6 o superior:

import itertools 

def all_combinations(any_list): 
    return itertools.chain.from_iterable(
     itertools.combinations(any_list, i + 1) 
     for i in xrange(len(any_list))) 

A continuación, puede llamar a este como tal:

# as a generator 
all_combinations([1,2,3]) # --> <itertools.chain at 0x10ef7ce10> 

# as a list 
list(all_combinations([1,2,3])) # --> [(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 

# as a list of lists 
[list(l) for l in all_combinations([1,2,3])] # --> [[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

Si no ha utilizado generadores antes, tenga en cuenta que los recorre como si fueran una lis t, como este:

# a generator returned instead of list 
my_combinations = all_combinations([1,2,3]) 

# this would also work if `my_combinations` were a list 
for c in my_combinations: 
    print "Combo", c 

""" 
Prints: 
    Combo (1,) 
    Combo (2,) 
    Combo (3,) 
    Combo (1, 2) 
    Combo (1, 3) 
    Combo (2, 3) 
    Combo (1, 2, 3) 
""" 

La diferencia de rendimiento puede ser dramático. Si se compara el rendimiento se verá que el generador es mucho más rápido para crear:

# as a generator 
all_combinations(range(25)) # timing: 100000 loops, best of 3: 2.53 µs per loop 

# as a list 
list(all_combinations(range(25))) # timing: 1 loops, best of 3: 9.37 s per loop 

Tenga en cuenta que no por ello deja tomar algún tiempo para recorrer todas las combinaciones en cualquiera de los casos, pero puede ser un gran gana para ti especialmente si encuentras lo que estás buscando al principio.

1
l = [1,2,3] 
combs = reduce(lambda x, y: list(itertools.combinations(l, y)) + x, range(len(l)+1), []) 

Si desea un oneliner.

Cuestiones relacionadas