python
October 19, 2022

Объединение простых структур данных в Python

Вы думаете, всё так просто? Да, всё просто. Но совсем не так... (Альберт Эйнштейн). Зачастую в работе в Python возникает необходимость в объединении простых структур данных. Расскажу, как сделать это изящно для списков, множеств и словарей без нагромождения лишних строк кода.

Эффективные решения для объединения двух элементов и списка из таких элементов могут быть разные, поэтому для каждого типа данных рассмотрим оба кейса.

Множества

Для множества разницы нет. С помощью метода union мы можем перечислить имеющиеся множества или распаковать их список:

items_l = [{12,32,44,55}, {5,2}]
set().union(items_l[0], items_l[1])
set().union(*items_l)

Более универсальным методом является использование функции chain модуля itertools, перебирающей элементы из всех составляющих списка:

from itertools import chain

set(chain(*items_l))

Списки

Для объединения двух списков можно использовать оператор "+"

items_l = [[12,32,44,55], [5,2]]

items_l[0]+items_l[1]

Для объединения списка списков воспользуйтесь все той же функцией chain:

list(chain(*items_l))

Еще можно адаптировать способ объединения двух списков с reduce из модуля functools, которая принимает функцию, последовательно обрабатывающую элементы итератора и в первом параметре сохраняет результат предыдущего шага:

from functools import reduce
reduce(lambda a, b: a+b, items_l)

Словари

Со словарями ситуация интереснее. Для объединения двух элементов в один можно распаковать их в новом словаре следующим образом:

items_l = [{12:1,32:2,44:3,55:4}, {5:1,2:3}]

{**items_l[0], **items_l[1]}

А вот в случае работы со списком чуть сложнее, обычное применение chain не поможет, так как итерация происходит по ключам:

dict(chain(*items_l))
list(chain(*items_l))

Но можно адаптировать входной параметр для применения с chain:

dict(chain(*[item.items() for item in items_l]))

или так:

dict(chain(*map(dict.items, items_l)))

Еще можно воспользоваться как и в случае со списками функцией reduce:

from functools import reduce
reduce(lambda a, b: {**a, **b}, items_l)

Также для объединения списка словарей можно воспользоваться классом ChainMap, который как раз заменяет chain для случая словарей и действует аналогично:

from collections import ChainMap
dict(ChainMap(*items_l))