Cómo obtener el producto cartesiano de múltiples listas
¿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.product
puede 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.product
luchan 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).
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)
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)
>>>
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())
[()]
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]]