но, насколько я знаю, все решения, кроме одного, терпят неудачу в списке типа [[[1, 2, 3], [4, 5]], 6], где находится желаемый результат [1, 2, 3, 4, 5, 6] (или, возможно, даже лучше, итератор).
Единственное решение, которое я видел, которое работает для произвольной вложенности, найдено в этом вопросе:
defflatten(x): result = [] for el in x: ifhasattr(el, "__iter__") andnotisinstance(el, basestring): result.extend(flatten(el)) else: result.append(el) return result
Это лучший подход? Я что-то упустил? Есть проблемы?
Переведено автоматически
Ответ 1
Использование функций генератора может облегчить чтение вашего примера и повысить производительность.
defflatten(xs): for x in xs: ifisinstance(x, Iterable) andnotisinstance(x, basestring): for item in flatten(x): yield item else: yield x
Python 3
В Python 3 basestring больше нет, но кортеж (str, bytes) дает тот же эффект. Кроме того, yield from оператор возвращает элемент из генератора по одному за раз.
from collections.abc import Iterable
defflatten(xs): for x in xs: ifisinstance(x, Iterable) andnotisinstance(x, (str, bytes)): yieldfrom flatten(x) else: yield x
Ответ 2
Мое решение:
import collections
defflatten(x): ifisinstance(x, collections.Iterable): return [a for i in x for a in flatten(i)] else: return [x]
Немного более лаконично, но практически то же самое.
Ответ 3
Генератор, использующий рекурсию и утиный ввод (обновлено для Python 3):
defflatten(L): for item in L: try: yieldfrom flatten(item) except TypeError: yield item
Вот моя функциональная версия recursive flatten, которая обрабатывает как кортежи, так и списки и позволяет вводить любое сочетание позиционных аргументов. Возвращает генератор, который выдает всю последовательность по порядку, аргумент за аргументом:
flatten = lambda *n: (e for a in n for e in (flatten(*a) ifisinstance(a, (tuple, list)) else (a,)))