Рубрики
Без рубрики

Питон: Как сгладить список списков

В этом уроке мы рассмотрим примеры того, как сгладить 2D-список (список списков) в один список. Мы будем использовать для циклов, понимания списков, рекурсивных алгоритмов, а также библиотек, таких как Numpy и functools.

Автор оригинала: Raksha Shenoy.

Питон: Как сгладить список списков

Вступление

Список – это самая гибкая структура данных в Python. В то время как 2D – список, который обычно известен как список списков, является объектом списка, где каждый элемент является самим списком- например: [[1,2,3], [4,5,6], [7,8,9]] .

Выравнивание списка списков влечет за собой преобразование 2D-списка в 1D – список путем удаления вложенности каждого элемента списка, хранящегося в списке списков, т. е. [[1, 2, 3], [4, 5, 6], [7, 8, 9]] в [1, 2, 3, 4, 5, 6, 7, 8, 9] .

Процесс выравнивания может быть выполнен с помощью вложенных циклов for, понимания списков, рекурсии, встроенных функций или путем импорта библиотек в Python в зависимости от регулярности и глубины вложенных списков.

Типы вложенных списков

Поскольку Python слабо типизирован, вы можете столкнуться с регулярными и нерегулярными списками списков.

Обычный список списков

Каждый элемент этого списка является подсписком, тем самым соблюдая единообразие типа элемента. Пример: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] представляет собой обычный список списков в виде [1, 2, 3], [4, 5, 6], [7, 8, 9] имеет тип список .

Нерегулярный список списков

Каждый элемент этого списка является либо подсписком, либо элементом, не входящим в список (например, целым числом или строкой). Следовательно, существует неравномерность с точки зрения типа элемента. Пример: [[1, 2, 3], [4, 5], 6] где [1, 2, 3] и [4, 5] имеют тип список и 6 имеет тип int .

Сглаживание списка списков с помощью вложенных циклов for

Это грубый подход к получению плоского списка путем выбора каждого элемента из списка списков и помещения его в 1D-список.

Код интуитивно понятен, как показано ниже, и работает как для регулярных, так и для нерегулярных списков списков:

def flatten_list(_2d_list):
    flat_list = []
    # Iterate through the outer list
    for element in _2d_list:
        if type(element) is list:
            # If the element is of type list, iterate through the sublist
            for item in element:
                flat_list.append(item)
        else:
            flat_list.append(element)
    return flat_list

nested_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
print('Original List', nested_list)
print('Transformed Flat List', flatten_list(nested_list))

Это приводит к:

Original List [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Transformed Flat List [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Сглаживание списка списков С помощью понимания списка

Этот подход обеспечивает элегантное, но менее интуитивное решение для создания плоского списка на основе существующего 2D-списка:

regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
flat_list = [item for sublist in regular_list for item in sublist]
print('Original list', regular_list)
print('Transformed list', flat_list)

Что привело бы к следующему результату:

Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]

Сглаживание списка списков рекурсивно

2D-список также может быть расплющен рекурсивно. Приведенная ниже реализация работает как для регулярного, так и для нерегулярного списка списков:

def flatten(list_of_lists):
    if len(list_of_lists) == 0:
        return list_of_lists
    if isinstance(list_of_lists[0], list):
        return flatten(list_of_lists[0]) + flatten(list_of_lists[1:])
    return list_of_lists[:1] + flatten(list_of_lists[1:])


print(flatten([[1, 2, 3, 4], [5, 6, 7], [8, 9], 10]))

Что дало бы нам:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Использование библиотек

Вы также можете положиться на помощь библиотек Pyhon для этой задачи.

Сгладить список списков с помощью functools (reduce() и i concat())

Функция concat() выполняет основную операцию конкатенации и применяется кумулятивно к элементам списка списков слева направо, чтобы свести его к одному списку:

import functools
import operator
regular_list = []

# Transform irregular 2D list into a regular one.
def transform(nested_list):
    for ele in nested_list:
        if type(ele) is list:
            regular_list.append(ele)
        else:
            regular_list.append([ele])
    return regular_list


irregular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10], 11]
regular_2D_list = transform(irregular_list)
print('Original list', irregular_list)
print('Transformed list', functools.reduce(operator.iconcat, regular_2D_list, []))

Что дало бы нам желаемый результат:

Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10], 11]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Сгладить список списков с помощью itertools (chain())

Этот подход идеально подходит для преобразования 2-D списка в единый плоский список, поскольку он рассматривает последовательные последовательности как единую последовательность, последовательно повторяя итерацию, передаваемую в качестве аргумента.

import itertools

regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
flat_list = list(itertools.chain(*regular_list))

print('Original list', regular_list)
print('Transformed list', flat_list)

Опять же, это дало бы нам сплющенный список в качестве вывода:

Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Сгладить список списков с помощью numpy (concatenate() и flat())

Numpy предлагает общие операции, которые включают конкатенацию регулярных 2D-массивов по строкам или столбцам. Мы также используем атрибут flat для получения 1D-итератора над массивом для достижения нашей цели. Однако этот подход является относительно медленным:

import numpy

regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]

flat_list = list(numpy.concatenate(regular_list).flat)

print('Original list', regular_list)
print('Transformed list', flat_list)

Что дает нам желаемый результат:

Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]

Использование Встроенных Функций

Задача выравнивания также может быть выполнена с помощью встроенных функций, которые предлагает Python.

Сгладить список списков с помощью sum

Суммирование по внутренним спискам-это еще одно решение. Функция имеет два параметра: iterable , который является списком списков, и start , который является пустым списком в нашем случае, который служит исходным плоским списком, к которому добавляются элементы внутренних подсписков.

Этот подход удобен тем, что вам не нужно ничего импортировать, но он медленнее, чем функции itertools() и chain() при большом количестве подсписков:

regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]

flat_list = sum(regular_list, [])

print('Original list', regular_list)
print('Transformed list', flat_list)

С выходом:

Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]

Сглаживание списка списков с помощью Лямбды

Анонимная функция может быть определена с помощью ключевого слова lambda. Регулярный/нерегулярный список передается в качестве аргумента этой анонимной функции, и вычисление выражения выполняется для получения плоского 1D-списка:

irregular_list = [[1, 2, 3], [3, 6, 7], [7, 5, 4],7]

# Using lambda arguments: expression
flatten_list = lambda irregular_list:[element for item in irregular_list for element in flatten_list(item)] if type(irregular_list) is list else [irregular_list]

print("Original list ", irregular_list)
print("Transformed List ", flatten_list(irregular_list))

Мы бы снова получили желаемый результат:

Original list  [[1, 2, 3], [3, 6, 7], [7, 5, 4], 7]
Transformed List  [1, 2, 3, 3, 6, 7, 7, 5, 4, 7]

Вывод

В этой статье мы представили обширный список способов, которыми мы можем выполнить задачу выравнивания списка списков в Python.