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

Как распрямить вложенный список в 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
Автор
Редакция

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

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро