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.