¿Cómo puedo obtener el producto cartesiano (todas las combinaciones posibles de valores) de un grupo de listas?
Entrada:
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) ...]
set(cartesian product)
set(inputlist)
sobre todas sus listas de entrada. No en el resultado.Respuestas:
itertools.product
Disponible desde Python 2.6.
Que es lo mismo que
fuente
product()
generanitems_in_a_list ** nlists
elementos en el resultado (reduce(mul, map(len, somelists))
). No hay ninguna razón para creer que producir un solo elemento no estáO(nlists)
(amortizado), es decir, la complejidad del tiempo es la misma que para losfor
bucles anidados simples , por ejemplo, para la entrada en la pregunta:,nlists=3
número total de elementos en el resultado:3*2*2
y cada elemento tienenlists
elementos (3
en este caso).*
somelistas anteriores? ¿Qué hace?fuente
Para Python 2.5 y anteriores:
Aquí hay una versión recursiva de
product()
(solo una ilustración):Ejemplo:
fuente
args
son iteradores.con itertools.product :
fuente
*
somelistas anteriores?Usaría la comprensión de la lista:
fuente
Aquí hay un generador recursivo, que no almacena ninguna lista temporal
Salida:
fuente
def f(): while True: yield 1
este seguirá aumentando su tamaño de pila a medida que avanzamos?En Python 2.6 y superior puedes usar 'itertools.product`. En versiones anteriores de Python, puede usar el siguiente código equivalente (casi ver documentación) de la documentación , al menos como punto de partida:
El resultado de ambos es un iterador, por lo que si realmente necesita una lista para el procesamiento adicional, úselo
list(result)
.fuente
Aunque ya hay muchas respuestas, me gustaría compartir algunos de mis pensamientos:
Enfoque iterativo
Enfoque recursivo
Enfoque Lambda
fuente
Enfoque recursivo:
Enfoque iterativo:
fuente
Una modificación menor a la solución del generador recursivo anterior en sabor variadic:
Y, por supuesto, un contenedor que hace que funcione exactamente igual que esa solución:
con una compensación : verifica si la recursión debe romperse en cada bucle externo, y una ganancia : no hay rendimiento en una llamada vacía, por ejemplo
product(())
, lo que supongo que sería semánticamente más correcto (ver el doctest).Con respecto a la comprensión de la lista: la definición matemática se aplica a un número arbitrario de argumentos, mientras que la comprensión de la lista solo puede tratar con un número conocido de ellos.
fuente
Solo para agregar un poco a lo que ya se ha dicho: si usa sympy, puede usar símbolos en lugar de cadenas, lo que los hace matemáticamente útiles.
Sobre sympy .
fuente
Creo que esto funciona:
fuente
Enfoque de Stonehenge:
salida:
fuente