Realice itertools.product permitiendo un número diferente de repeticiones para diferentes iterables.
Supongamos que tengo dos iterables A = 'ab'
y B = '12'
.
itertools.product
devuelve un iterador que generará el producto cartesiano de A
y B
; por ejemplo:
>>> list(itertools.product(A,B))
[('a', '1'), ('a', '2'), ('b', '1'), ('b', '2')].
La función tiene un argumento opcional de palabra clave repeat
, que se puede utilizar para encontrar el producto cartesiano de un iterable consigo mismo; por ejemplo:
>>> list(itertools.product(A,repeat=2))
[('a', 'a'), ('a', 'b'), ('b', 'a'), ('b', 'b')]
y es equivalente a list(itertools.product(A,A))
.
Luego, utilizando repeat=2
y tanto A
como B
, se obtiene:
>>> list(itertools.product(A,B,repeat=2))
[('a', '1', 'a', '1'), ('a', '1', 'a', '2'), ('a', '1', 'b', '1'), ('a', '1', 'b', '2'), ('a', '2', 'a', '1'), ('a', '2', 'a', '2'), ('a', '2', 'b', '1'), ('a', '2', 'b', '2'), ('b', '1', 'a', '1'), ('b', '1', 'a', '2'), ('b', '1', 'b', '1'), ('b', '1', 'b', '2'), ('b', '2', 'a', '1'), ('b', '2', 'a', '2'), ('b', '2', 'b', '1'), ('b', '2', 'b', '2')]
y es equivalente a list(itertools.product(A,B,A,B))
.
Pero ahora supongamos que quiero encontrar el producto cartesiano de n_A
repeticiones de A
y n_B
repeticiones de B
, donde n_A
y n_B
no tienen que ser iguales. ¿Cómo puedo hacer esto? Sería genial si repeat
aceptara la tupla (n_A, n_B)
y pudiera escribir:
list(itertools.product(A,B,repeat=(n_A,n_B)))
por ejemplo:
list(itertools.product(A,B,repeat=(2,3))) == list(itertools.product(A,A,B,B,B))
pero esto no parece estar permitido.
Ten en cuenta que técnicamente (A,A,B,B,B)
es un producto diferente a (A,B,A,B,B)
, sin embargo, de todas formas ordenaré las salidas, así que no me importa el orden de los datos de entrada.
davy.ai
Para encontrar la combinación cartesiana de
n_A
repeticiones deA
yn_B
repeticiones deB
, puedes utilizar la comprensión de listas dentro deitertools.product
. Crea una lista de iterables que contengan_A
copias deA
yn_B
copias deB
, y pasa esta lista como argumento*iterables
aitertools.product
. Así es como puedes hacerlo:Esto te dará el mismo resultado que
list(itertools.product(A,A,B,B,B))
, pero sin tener que codificar las iterables individuales. Puedes cambiar fácilmente los valores den_A
yn_B
para generar diferentes productos.Ten en cuenta que el operador
*
se utiliza para desempaquetar la lista de iterables en argumentos separados paraitertools.product
. Esto se debe a queproduct
acepta argumentos variables, mientras que pasar una lista de iterables como un único argumento resultará en una combinación cartesiana de los elementos de la lista, en lugar de los iterables individuales en sí.