Подтвердить что ты не робот

В чем разница между цепочкой и цепочкой. В зависимости от типа itertools?

Я не мог найти никакого действительного примера в Интернете, где я вижу разницу между ними и почему выбирать один из них.

4b9b3361

Ответ 1

Первый принимает 0 или более аргументов, каждый из которых является итерируемым, второй - один аргумент, который, как ожидается, создаст итерируемые:

from itertools import chain

chain(list1, list2, list3)

iterables = [list1, list2, list3]
chain.from_iterable(iterables)

но iterables могут быть любыми итераторами, которые дают итерации:

def gen_iterables():
    for i in range(10):
        yield range(i)

itertools.chain.from_iterable(gen_iterables())

Использование второй формы обычно удобно для удобства, но поскольку она циклически повторяется во входных итерациях, это также единственный способ связать бесконечное число конечных итераторов:

def gen_iterables():
    while True:
        for i in range(5, 10):
            yield range(i)

chain.from_iterable(gen_iterables())

Приведенный выше пример даст вам итерацию, которая дает циклический шаблон чисел, который никогда не остановится, но никогда не будет занимать больше памяти, чем требуется для одного вызова range().

Ответ 2

Они делают очень похожие вещи. Для небольшого числа итераций itertools.chain(*iterables) и itertools.chain.from_iterable(iterables) выполняются аналогично.

Основное преимущество from_iterables заключается в способности обрабатывать большое (потенциально бесконечное) количество итераций, поскольку все они не должны быть доступны во время вызова.

Ответ 3

Я не смог найти ни одного действительного примера... где я вижу разницу между ними [ chain и chain.from_iterable ] и почему нужно выбирать один над другим

Принятый ответ является тщательным. Для тех, кто ищет быстрое приложение, рассмотрите сглаживание нескольких списков:

list(itertools.chain(["a", "b", "c"], ["d", "e"], ["f"]))
# ['a', 'b', 'c', 'd', 'e', 'f']

Вы можете захотеть использовать эти списки позже, поэтому вы создаете итерируемые списки:

iterable = (["a", "b", "c"], ["d", "e"], ["f"])

попытка

Тем не менее, передача итерируемой по chain приводит к непредсказуемому результату:

list(itertools.chain(iterable))
# [['a', 'b', 'c'], ['d', 'e'], ['f']]

Зачем? Вы передали один предмет (кортеж). chain нужен каждый список в отдельности.


Решения

По возможности вы можете распаковать итерацию:

list(itertools.chain(*iterable))
# ['a', 'b', 'c', 'd', 'e', 'f']

list(itertools.chain(*iter(iterable)))
# ['a', 'b', 'c', 'd', 'e', 'f']

В более общем случае используйте .from_iterable (поскольку он также работает с бесконечными итераторами):

list(itertools.chain.from_iterable(iterable))
# ['a', 'b', 'c', 'd', 'e', 'f']

g = itertools.chain.from_iterable(itertools.cycle(iterable))
next(g)
# "a"

Ответ 4

Еще один способ увидеть это:

chain(iterable1, iterable2, iterable3,...) предназначена для chain(iterable1, iterable2, iterable3,...) когда вы уже знаете, какие у вас есть итерируемые элементы, поэтому вы можете записать их в качестве аргументов, разделенных запятыми.

chain.from_iterable(iterable) предназначен для случаев, когда ваши итерируемые объекты (например, iterable1, iterable2, iterable3) получены из другого итерируемого элемента.