Cómo obtener el producto cartesiano de múltiples listas

Resuelto ʞɔıu asked hace 15 años • 20 respuestas

¿Cómo puedo obtener el producto cartesiano (todas las combinaciones posibles de valores) de un grupo de listas?

Por ejemplo, dado

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]

¿Cómo consigo esto?

[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), (2, 'a', 5), ...]

Una aplicación común de esta técnica es evitar bucles profundamente anidados. Consulte Evitar bucles for anidados para obtener un duplicado más específico. De manera similar, esta técnica podría usarse para "explotar" un diccionario con valores de lista; consulte Combinar permutaciones del diccionario Python en una lista de diccionarios .

Si desea un producto cartesiano de la misma lista consigo mismo varias veces, itertools.productpuede manejarlo con elegancia. Consulte Operación en cada par de elementos de una lista o ¿Cómo puedo obtener "permutaciones con repeticiones" de una lista (producto cartesiano de una lista consigo misma)? .

Muchas personas que ya saben sobre esto itertools.productluchan con el hecho de que espera argumentos separados para cada secuencia de entrada, en lugar de, por ejemplo, una lista de listas. La respuesta aceptada muestra cómo manejar esto con *. Sin embargo, el uso de *aquí para descomprimir argumentos no es fundamentalmente diferente de cualquier otro momento en el que se usa en una llamada de función. Consulte Expandir tuplas en argumentos para este tema (y utilícelo en su lugar para cerrar preguntas duplicadas, según corresponda).

ʞɔıu avatar Feb 11 '09 02:02 ʞɔıu
Aceptado

Use itertools.product, que ha estado disponible desde Python 2.6.

import itertools

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]
for element in itertools.product(*somelists):
    print(element)

Esto es lo mismo que:

for element in itertools.product([1, 2, 3], ['a', 'b'], [4, 5]):
    print(element)
Kenan Banks avatar Feb 10 '2009 19:02 Kenan Banks
import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
...         print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>
Jason Baker avatar Feb 10 '2009 19:02 Jason Baker

Para Python 2.5 y versiones anteriores:

>>> [(a, b, c) for a in [1,2,3] for b in ['a','b'] for c in [4,5]]
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), 
 (2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5), 
 (3, 'b', 4), (3, 'b', 5)]

Aquí hay una versión recursiva de product()(solo una ilustración):

def product(*args):
    if not args:
        return iter(((),)) # yield tuple()
    return (items + (item,) 
            for items in product(*args[:-1]) for item in args[-1])

Ejemplo:

>>> list(product([1,2,3], ['a','b'], [4,5])) 
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), 
 (2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5), 
 (3, 'b', 4), (3, 'b', 5)]
>>> list(product([1,2,3]))
[(1,), (2,), (3,)]
>>> list(product([]))
[]
>>> list(product())
[()]
jfs avatar Feb 10 '2009 20:02 jfs

Yo usaría lista de comprensión :

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]

cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]
user1035648 avatar Nov 21 '2016 08:11 user1035648