ʞɔıu
¿Cómo puedo obtener el producto cartesiano (todas las combinaciones posibles de valores) de un grupo de listas?
Aporte:
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
Salida deseada:
[(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.
Si desea un producto cartesiano de lo mismo lista consigo mismo varias veces, itertools.product
puede manejar eso con elegancia. Ver Operación en cada par de elementos en una lista o Generación de permutaciones con repeticiones.
Bancos de Kenan
Usar 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)
-
Solo quería agregar el carácter ‘*’ si usa la variable somelists según lo proporcionado por el OP.
– brian dólar
13 de enero de 2011 a las 22:51
-
Cuál es el uso de
*
antes de algunas listas? ¿Qué hace?– Vineet Kumar Doshi
25 de agosto de 2015 a las 9:04
-
@VineetKumarDoshi: Aquí se usa para descomponer una lista en múltiples argumentos para la llamada a la función. Lea más aquí: stackoverflow.com/questions/36901/…
– Moberg
15 de septiembre de 2015 a las 6:20
-
Nota: Esto funciona solo si cada lista contiene al menos un elemento
– Yo voy
13/09/2017 a las 12:35
-
@igo también funciona cuando cualquier lista contiene cero elementos: el producto cartesiano de al menos una lista de tamaño cero y cualquier otra lista es una lista vacía, y eso es exactamente lo que esto produce.
– Ruzihm
9 oct 2019 a las 20:42
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)
>>>
jfs
Para Python 2.5 y 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())
[()]
-
La versión recursiva no funciona si algunos de
args
son iteradores.– jfs
10 de febrero de 2009 a las 21:43
Yo usaría la 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]]
Fantasma silencioso
con itertools.producto:
import itertools
result = list(itertools.product(*somelists))
-
Cuál es el uso de
*
antes de algunas listas?– Vineet Kumar Doshi
25 de agosto de 2015 a las 9:04
-
@VineetKumarDoshi “producto(algunas listas)” es un producto cartesiano entre las sublistas de manera que Python obtiene primero “[1, 2, 3]” como un elemento y luego obtiene otro elemento después del siguiente comando y ese es el salto de línea, por lo que el primer término del producto es ([1, 2, 3],), similarmente para el segundo ([4, 5],) y entonces “[([1, 2, 3],), ([4, 5],), ([6, 7],)]”. Si desea obtener un producto cartesiano entre elementos dentro de las tuplas, debe informar a Python con Asterisk sobre la estructura de la tupla. Para el diccionario, usa **. Más aquí.
– hhh
15 de febrero de 2016 a las 23:13
Anurag Uniyal
Aquí hay un generador recursivo, que no almacena ninguna lista temporal.
def product(ar_list):
if not ar_list:
yield ()
else:
for a in ar_list[0]:
for prod in product(ar_list[1:]):
yield (a,)+prod
print list(product([[1,2],[3,4],[5,6]]))
Producción:
[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]
-
Cuál es el uso de
*
antes de algunas listas?– Vineet Kumar Doshi
25 de agosto de 2015 a las 9:04
-
@VineetKumarDoshi “producto(algunas listas)” es un producto cartesiano entre las sublistas de manera que Python obtiene primero “[1, 2, 3]” como un elemento y luego obtiene otro elemento después del siguiente comando y ese es el salto de línea, por lo que el primer término del producto es ([1, 2, 3],), similarmente para el segundo ([4, 5],) y entonces “[([1, 2, 3],), ([4, 5],), ([6, 7],)]”. Si desea obtener un producto cartesiano entre elementos dentro de las tuplas, debe informar a Python con Asterisk sobre la estructura de la tupla. Para el diccionario, usa **. Más aquí.
– hhh
15 de febrero de 2016 a las 23:13
En Python 2.6 y superior, puede usar ‘itertools.product`. En versiones anteriores de Python, puede usar el siguiente equivalente (casi, consulte la documentación) código de la documentaciónal menos como punto de partida:
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
El resultado de ambos es un iterador, por lo que si realmente necesita una lista para un procesamiento posterior, use list(result)
.
-
Según la documentación, la implementación real de itertools.product NO genera resultados intermedios, lo que podría ser costoso. El uso de esta técnica podría salirse de control con bastante rapidez para las listas de tamaño moderado.
– Kenan Banks
10 de febrero de 2009 a las 20:05
-
Solo puedo señalar el OP a la documentación, no leerlo por él.
– usuario3850
10 de febrero de 2009 a las 20:19
-
El código de la documentación está destinado a demostrar lo que hace la función del producto, no como una solución para versiones anteriores de Python.
– Kenan Banks
10 de marzo de 2009 a las 21:07
tenga en cuenta que ‘todas las combinaciones posibles’ no es lo mismo que ‘producto cartesiano’, ya que en los productos cartesianos se permiten duplicados.
– Kenan Banks
10 de febrero de 2009 a las 20:08
¿Existe una versión no duplicada del producto cartesiano?
– KJW
13 de noviembre de 2013 a las 5:32
@KJW Sí,
set(cartesian product)
– Sin errores
12 de febrero de 2015 a las 7:04
No debe haber duplicados en un producto cartesiano, a menos que las listas de entrada contengan duplicados. Si no desea duplicados en el producto cartesiano, utilice
set(inputlist)
sobre todas sus listas de entrada. No en el resultado.– CamilB
24 de agosto de 2017 a las 8:39
Matemáticamente, un producto cartesiano es un conjunto, por lo que un producto cartesiano no no contienen duplicados. Por otra parte,
itertools.product
tendrá duplicados en la salida si las entradas tienen duplicados. Asi queitertools.product
no es estrictamente hablando el producto cartesiano, a menos que envuelva las entradas enset
como lo menciona @CamilB.–Cameron Bieganek
8 dic 2020 a las 22:56