tag - python html parser
¿Cuál es la diferencia entre cadena y cadena? (4)
No pude encontrar ningún ejemplo válido ... donde puedo ver la diferencia entre ellos [
chain
ychain.from_iterable
] y por qué elegir uno sobre el otro
La respuesta aceptada es minuciosa. Para aquellos que buscan una aplicación rápida, considere aplanar varias listas:
list(itertools.chain(["a", "b", "c"], ["d", "e"], ["f"]))
# [''a'', ''b'', ''c'', ''d'', ''e'', ''f'']
Si lo desea, puede reutilizar estas listas más adelante, de modo que haga una iterable de listas:
iterable = (["a", "b", "c"], ["d", "e"], ["f"])
Intento
Sin embargo, pasar en un iterable para chain
da un resultado no aplanado:
list(itertools.chain(iterable))
# [[''a'', ''b'', ''c''], [''d'', ''e''], [''f'']]
¿Por qué? Pasaste en un artículo (una tupla). chain
necesita cada lista por separado.
Soluciones
Cuando sea posible, puede descomprimir un iterable:
list(itertools.chain(*iterable))
# [''a'', ''b'', ''c'', ''d'', ''e'', ''f'']
list(itertools.chain(*iter(iterable)))
# [''a'', ''b'', ''c'', ''d'', ''e'', ''f'']
Más generalmente, use .from_iterable
(ya que también funciona con infinitos iteradores):
list(itertools.chain.from_iterable(iterable))
# [''a'', ''b'', ''c'', ''d'', ''e'', ''f'']
g = itertools.chain.from_iterable(itertools.cycle(iterable))
next(g)
# "a"
No pude encontrar ningún ejemplo válido en Internet donde pueda ver la diferencia entre ellos y por qué elegir uno sobre el otro.
El primero toma 0 o más argumentos, cada uno es iterable, el segundo toma un argumento que se espera que produzca los iterables:
itertools.chain(list1, list2, list3)
iterables = [list1, list2, list3]
itertools.chain.from_iterable(iterables)
pero iterables
puede ser cualquier iterador que produzca los iterables.
def generate_iterables():
for i in range(10):
yield range(i)
itertools.chain.from_iterable(generate_iterables())
El uso de la segunda forma suele ser un caso de conveniencia, pero debido a que recorre perezosamente los iterables de entrada, también es la única manera de encadenar un número infinito de iteradores finitos:
def generate_iterables():
while True:
for i in range(5, 10):
yield range(i)
itertools.chain.from_iterable(generate_iterables())
El ejemplo anterior le proporcionará un iterable que produce un patrón cíclico de números que nunca se detendrán, pero nunca consumirá más memoria de lo que requiere una llamada de un solo range()
.
Hacen cosas muy similares. Para un pequeño número de iterables, itertools.chain(*iterables)
y itertools.chain.from_iterable(iterables)
funcionan de manera similar.
La ventaja clave de from_iterables
reside en la capacidad de manejar un gran número (potencialmente infinito) de iterables, ya que no es necesario que todos estén disponibles en el momento de la llamada.
Otra forma de verlo:
chain(iterable1, iterable2, iterable3, ...)
es para cuando ya sabe qué iterables tiene, por lo que puede escribirlos como estos argumentos separados por comas.
chain.from_iterable(iterable)
es para cuando sus iterables (como iterable1, iterable2, iterable3) se obtienen de otro iterable.