Łączenie list w Python


Jak łączyć wiele list w Python, czyli chain z biblioteki standardowej itertools.


tl;dr - itertools.chain(* iterables )

Przetwarzając dane bardzo szybko dojdziesz do sytuacji w której będziesz musiał operować na kilku listach.

Proste podejście

Spróbujmy podejść do pisania bloga jak do tablicy Kanbanowej w której mamy 3 kolumny (do realizacji, w trakcie oraz zrealizowane). Jako zadanie spróbujmy zebrać listę wszystkich wpisów niezależnie od statusu i zbudujmy z tego płaską listę.

to_do = ["słowniki w Python"]
in_progress = ["collections.Counter w Python", "itertools.chain w Python"]
done = ["kalkulator w Python", "błędy z get w dict"]

# dodawanie
tasks = to_do + in_progress + done
print(tasks)  # ['słowniki w Python', 'collections.Counter w Python', 'itertools.chain w Python', 'kalkulator w Python', 'błędy z get w dict']

# extend
tasks = [] 
tasks.extend(to_do)
tasks.extend(in_progress)
tasks.extend(done)
print(tasks)  # ['słowniki w Python', 'collections.Counter w Python', 'itertools.chain w Python', 'kalkulator w Python', 'błędy z get w dict']

Dynamiczna długość listy - extend

Powyższe rozwiązania są stosunkowo proste, bo mamy z góry zdefiniowane listy, które musimy dodawać. Problem pojawia się w momencie gdy nie wiemy ile list musimy ze sobą połączyć. Tu już będzie ciężko dodawać, ale przy pomocy extend dalej jesteśmy w stanie obsłużyć. Dla przykładu spróbujmy zbudować tabliczkę mnożenia, a następnie z tej tabliczki mnożenia zróbmy płaską listę.

Tabliczkę mnożenia tworzyłem już w moim pierwszy wpisie , dlatego tu wkleję jak to zrobić bez głębszego tłumaczenia

table = lambda size: [[col*row for col in range(1, size)] for row in range(1, size)]
table(5)  # [[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16]]

A teraz jak to połączyć przez extend

flat_list = []
for row in table(5):
    flat_list.extend(row)

print(flat_list)  # [1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16]

Chain w itertools

Powyższe rozwiązaine nie wygląda źle. Ale możemy to zrobić zgrabniej, bo przy użyciu wbudowanej biblioteki itertools i funkcji chain .

flat_list = itertools.chain(*table(5))
print(list(flat_list))  # [1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16]

Jak widać wystarczyło rozpakować listę i cała magia dzieje się sama.

W związku z tym, że chain zwraca generator musiałem zrzucić wynik na listę.

chain.from_iterable

Jeśli rozpakowanie listy wydało Ci się trochę przekombinowane to uwierz, nie jesteś jedny ;). Ale i na to jest rozwiązanie, istnieje bowiem opcja zrobienia tego prościej

flat_list = itertools.chain.from_iterable(table(5))
print(list(flat_list))  # [1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16]

Chain a znane listy

Nic nie stoi na przeszkodzie, żeby chain używać również do zdefiniowanych już list zobaczmy to zresztą na poprzednim zadaniu

tasks = itertools.chain(to_do, in_progress, done)
print(list(tasks))  # 'słowniki w Python', 'collections.Counter w Python', 'itertools.chain w Python', 'kalkulator w Python', 'błędy z get w dict']

Podsumowanie

Tym krótkim wpisem chciałem zaprezentować Ci możliwości chain z biblioteki itertools. Odsyłam Cię i gorąca zachęcam do poznania innych funkcji, bo biblioteki wbudowane to bardzo przydatne narzędzie, które nie raz potrafi uprościć kod.

Kwi 23, 2020

Najnowsze wpisy

Zobacz wszystkie