tuplas - llenar una lista en python
Combinaciones de listas anidadas (3)
Como comentó @BrenBarn, puedes aplanar la lista y
con la función de chain
, y luego usar el product
:
from itertools import product, chain
list(product(x, chain.from_iterable(y)))
# [(''d'', ''f''), (''d'', ''1''), (''d'', ''2''), (''e'', ''f''), (''e'', ''1''), (''e'', ''2'')]
Tengo tres listas que son generadas por otras funciones. Supongamos por el momento que son:
x = [''d'', ''e'']
g = [''1'', ''2'']
y = [''f'', g]
Como puede ver, g
es parte de y
. Estoy tratando de obtener todas las combinaciones de los elementos de las tres listas. He intentado hacer esto de dos maneras:
De una sola mano:
l = []
l.append([a]+[b] for a in x for b in y)
Otra forma de usar itertools:
import itertools
l = list(itertools.product([a for a in x], [b for b in y]))
Ambas formas producen las siguientes combinaciones:
[(''d'', ''f''), (''d'', [''1'', ''2'']), (''e'', ''f''), (''e'', [''1'', ''2''])]
Pero lo que me gustaría obtener es:
[(''d'', ''f''), (''d'', ''1''), (''d'',''2''), (''e'', ''f''), (''e'', ''1''), (''e'',''2'')]
Además, cuando x
por ejemplo, está vacío, no obtengo ninguna combinación cuando todavía estoy esperando obtener las combinaciones de elementos de las dos listas restantes.
Me gustaría señalar dos implementaciones para funciones similares a flatten disponibles en more_itertools
(instalar a través de pip install more_itertools
).
flatten
es una receta itertools
y emula la propuesta de @ Psidom:
import itertools as it
import more_itertools as mit
list(it.product(x, mit.flatten(y)))
# [(''d'', ''f''), (''d'', ''1''), (''d'', ''2''), (''e'', ''f''), (''e'', ''1''), (''e'', ''2'')]
Sin embargo, para alisar iterables anidados más profundos, considere usar collapse
:
# Example
x = [''d'', ''e'']
g = [(''1''), [[[''2'']]]]
y = [{''f''}, g]
# Bad
list(it.product(x, mit.flatten(y)))
# [(''d'', ''f''), (''d'', ''1''), (''d'', [[[''2'']]]), (''e'', ''f''), (''e'', ''1''), (''e'', [[[''2'']]])]
# Good
list(it.product(x, mit.collapse(y)))
# [(''d'', ''f''), (''d'', ''1''), (''d'', ''2''), (''e'', ''f''), (''e'', ''1''), (''e'', ''2'')]
Esto está inspirado en la respuesta de @Psidoms, pero solo usa una función de flatten
específicamente diseñada para garantizar que solo se iteren los elementos que se deben flatten
:
def flatten(x, types=list):
lst = []
for item in x:
if isinstance(item, types):
for subitem in item:
lst.append(subitem)
else:
lst.append(item)
return lst
>>> from itertools import product
>>> list(product(x, flatten(y)))
[(''d'', ''f''), (''d'', ''1''), (''d'', ''2''), (''e'', ''f''), (''e'', ''1''), (''e'', ''2'')]
Tenga en cuenta que desafortunadamente no existe esa función de flatten
en la biblioteca estándar, pero también podría usar una de una biblioteca externa, por ejemplo iteration_utilities.deepflatten
. Tenga en cuenta que esto requiere proporcionar str
o basestring
como ignore
:
>>> from iteration_utilities import deepflatten
>>> list(product(x, deepflatten(y, ignore=str)))
[(''d'', ''f''), (''d'', ''1''), (''d'', ''2''), (''e'', ''f''), (''e'', ''1''), (''e'', ''2'')]
Para excluir los elementos iterables vacíos del producto, simplemente excluya los elementos secundarios vacíos. Por ejemplo:
>>> x = []
>>> iterables = [subiterable for subiterable in (x, list(deepflatten(y, ignore=str))) if subiterable]
>>> list(product(*iterables))
[(''f'',), (''1'',), (''2'',)]