Гид по технологиям

Как распрямить вложенный список в Python

3 min read Python Обновлено 05 Dec 2025
Распрямление вложенных списков в Python
Распрямление вложенных списков в Python

Блоки кода в редакторе

TL;DR — коротко

Рассмотрены практичные способы превращения вложенного списка в «плоский» в Python: простой одинарный concat через sum(), явный цикл или list comprehension, а также более надёжные способы — itertools.chain и рекурсивная функция для глубокой вложенности. Важно учитывать типы элементов (строки, словари) и производительность.

Задача

Вложенный список — это список, содержащий другие итерируемые объекты (списки, кортежи, множества, словари и т. п.). Цель — получить единый список с элементами верхнего уровня, то есть «распрямить» структуру.

Ключевые варианты решения: суммирование списков, цикл / list comprehension, itertools.chain, рекурсивное разворачивание для произвольной глубины.

Подход 1 — sum() для списка списков

Подходит, когда у вас ровно список списков (list of list). Метод прост и читаем:

nested_list = [[1, 3, 4], [2, 4], [7, 9, 0]]
flat_list = sum(nested_list, [])
print(flat_list)
# Вывод: [1, 3, 4, 2, 4, 7, 9, 0]

Важно: sum() выполняет конкатенацию списков и при большом объёме данных может быть медленнее из‑за многократных копирований. Он не работает для списков с кортежами, множествами или словарями, если вы ожидаете конкатенации разных типов.

Подход 2 — цикл for или list comprehension

Работает для последовательностей разного типа: list, tuple, set, а также для итерации по ключам словаря (обратите внимание, что при итерации по словарю по умолчанию возвращаются ключи).

Явный цикл:

nested_list = [[1, 3, 4], (1, 5, 6), {1, 2, 4}, {"e": 3, "o": 9, "t": 7}]
flat_list = []
for i in nested_list:
    for k in i:
        flat_list.append(k)

print(flat_list)
# Возможный вывод: [1, 3, 4, 1, 5, 6, 1, 2, 4, 'e', 'o', 't']

И тот же результат через list comprehension:

flat_list = [k for i in nested_list for k in i]
print(flat_list)

Совет: чтобы получить значения словаря, итерируйтесь по .values() или .items() в зависимости от нужд.

Подход 3 — itertools.chain для эффективной конкатенации

Если требуется объединить последовательности ровно на один уровень вложенности и вы заботитесь о производительности, используйте itertools.chain.from_iterable:

import itertools
nested_list = [[1, 3, 4], [2, 4], [7, 9, 0]]
flat_list = list(itertools.chain.from_iterable(nested_list))
print(flat_list)

chain.from_iterable выполняет конкатенацию без лишних копирований и обычно быстрее, чем sum при больших входных данных.

Подход 4 — рекурсивная распаковка для произвольной глубины

Если вложенность может быть произвольной (списки внутри списков внутри списков и т. д.), используйте рекурсию или стек. При этом осторожно обходите строки и байты — их лучше не рассматривать как коллекции символов.

Простой рекурсивный генератор, который не распадается на символы строк:

from collections.abc import Iterable

def flatten(iterable):
    for item in iterable:
        if isinstance(item, (list, tuple, set)):
            yield from flatten(item)
        else:
            yield item

nested = [1, [2, [3, 4], 'abc'], (5, 6)]
print(list(flatten(nested)))
# Вывод: [1, 2, 3, 4, 'abc', 5, 6]

Если нужно безопасно обходить любые итерируемые, кроме строк и байтов:

def flatten_safe(iterable):
    for item in iterable:
        if isinstance(item, Iterable) and not isinstance(item, (str, bytes, bytearray)):
            yield from flatten_safe(item)
        else:
            yield item

Когда методы дают неожиданный результат

  • sum() поддерживает только конкатенацию списков; для других типов он приведёт к TypeError.
  • Итерирование по словарю возвращает ключи; чтобы получить значения — используйте dict.values().
  • Строки и байты являются итерируемыми: рекурсивная распаковка может разбить строку по символам, если этого не учитывать.
  • Для очень больших структур рекурсивный подход может вызвать переполнение стека; используйте итеративный алгоритм или увеличьте лимит рекурсии с осторожностью.

Критерии приёмки (тесты)

  1. Вход: [[1,2],[3]] -> ожидаемый выход: [1,2,3]
  2. Вход: [1,(2,3),{4,5}] -> выход содержит все элементы из кортежа и множества (порядок множества не гарантирован)
  3. Вход с словарём: [{‘a’:1},{‘b’:2}] -> ожидаемое при итерации по ключам: [‘a’,’b’]; при использовании .values(): [1,2]
  4. Глубокая вложенность: [1,[2,[3,[4]]]] -> корректный плоский список [1,2,3,4]

Личные рекомендации и эвристики

  • Если у вас всё — списки одного уровня: используйте itertools.chain.from_iterable для скорости и читаемости.
  • Если данные смешанные или вложенность неизвестна — пишите явный рекурсивный генератор с исключением строк.
  • Избегайте sum() для больших объёмов или смешанных типов.

Краткий глоссарий

  • Плоский список — список без вложенных итерируемых контейнеров.
  • chain.from_iterable — функция из itertools для эффективного «склеивания» последовательностей.
  • Рекурсия — функция, вызывающая сама себя для обхода любой глубины структуры.

Итог

Распрямление вложенных списков в Python можно решить простыми приёмами (sum, цикл, list comprehension), а можно выбрать более универсальные и производительные варианты (itertools.chain, рекурсивный генератор). Выбор зависит от формата входа, объёма данных и требований к порядку элементов.

Важно: всегда тестируйте на граничных случаях — словари, строки, очень глубокая вложенность.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как устроить идеальную вечеринку для просмотра ТВ
Развлечения

Как устроить идеальную вечеринку для просмотра ТВ

Как распаковать несколько RAR‑файлов сразу
Инструменты

Как распаковать несколько RAR‑файлов сразу

Приватный просмотр в Linux: как и зачем
Приватность

Приватный просмотр в Linux: как и зачем

Windows 11 не видит iPod — способы исправить
Руководство

Windows 11 не видит iPod — способы исправить

PS5: как настроить игровые пресеты
Консоли

PS5: как настроить игровые пресеты

Как переключить камеру в Omegle на iPhone и Android
Руководство

Как переключить камеру в Omegle на iPhone и Android