Funkcionální programování v Pythonu s využitím knihovny Toolz (2. část)

22. 2. 2024
Doba čtení: 40 minut

Sdílet

Autor: Depositphotos
Ve druhém článku o knihovně Toolz, která podporuje funkcionální paradigma v jazyku Python, dokončíme popis podbalíčku itertoolz, jenž obsahuje funkce (a vlastně nic jiného než funkce) určené pro zpracování a analýzu sekvencí.

Obsah

1. Funkcionální programování v Pythonu s využitím knihovny Toolz (2. část)

2. Získání četnosti prvků v sekvenci

3. Rozdělení sekvence na základě výsledků funkce aplikované na prvky

4. Rozdělení prvků nekonečné sekvence

5. Posuvné okno nad sekvencí

6. Posuvné okno a nekonečná vstupní sekvence

7. Nalezení unikátních prvků v sekvenci

8. Test, zda sekvence obsahuje unikátní prvky

9. Rozdíl mezi operací partition a partition_all

10. Operace get

11. Operace pluck

12. Spojení sekvencí na základě klíčů (join)

13. Vylepšení tisku výsledku operace join

14. Vnitřní spojení (inner join)

15. Vnější spojení (outer join)

16. Obsah navazujícího článku

17. Repositář s demonstračními příklady

18. Odkazy na Internetu

1. Funkcionální programování v Pythonu s využitím knihovny Toolz (2. část)

Ve druhém článku o knihovně Toolz, která podporuje funkcionální paradigma v programovacím jazyku Python, dokončíme popis podbalíčku itertoolz, jenž obsahuje funkce (a vlastně nic jiného než funkce) určené pro zpracování a analýzu sekvencí. Uveďme si pro úplnost všechny funkce z tohoto podbalíčku, které jsme si buď již popsali minule či které si popíšeme v dnešním článku:

Operace Popsáno Stručný popis
first čl.8, kapitola 5 vrátí první prvek ze sekvence
last čl.8, kapitola 5 vrátí poslední prvek ze sekvence (pokud je konečná)
take čl.8, kapitola 5 vrátí prvních n prvků ze sekvence
drop čl.8, kapitola 5 vrátí sekvenci bez prvních n prvků
nth čl.8, kapitola 5 vrátí n-tý prvek ze sekvence
get čl.8, kapitola 5 vrátí n-tý prvek ze sekvence, výběr ze slovníku podle klíče, dokáže pracovat s neznámými hodnotami
     
iterate čl.8, kapitola 6 generování nekonečné sekvence
interleave čl.8, kapitola 8 kombinace většího množství sekvencí
groupby čl.8, kapitola 10 rozdělení prvků sekvence do skupin
partition čl.8, kapitola 12 rozdělení prvků sekvence do většího množství sekvencí
interpose čl.8, kapitola 14 proložení prvků sekvence další hodnotou
accumulate čl.8, kapitola 16 postupná redukce vstupu s akumulací mezivýsledků
diff čl.8, kapitola 17 výpočet rozdílu mezi sekvencemi
     
frequencies čl.9, kapitola 2 získání četnosti prvků v sekvenci
partitionby čl.9, kapitola 3 rozdělení sekvence na základě výsledků funkce aplikované na prvky
sliding_window čl.9, kapitola 5 posuvné okno nad sekvencí
unique čl.9, kapitola 7 nalezení unikátních prvků v sekvenci
isdistinct čl.9, kapitola 8 test, zda sekvence obsahuje unikátní prvky
partition_all čl.9, kapitola 9 rozdělení prvků sekvence do většího množství sekvencí
get čl.9, kapitola 10 zobecněná operace get (čtení dat ze sekvence nebo slovníku)
pluck čl.9, kapitola 11 opakovaná operace get pro všechny prvky sekvence
join čl.9, kapitola 12 vnitřní nebo vnější spojení (inner join, outer join)

2. Získání četnosti prvků v sekvenci

Velmi užitečná může být v praxi funkce nazvaná frequencies. Název této funkce naznačuje, jaký výpočet se provádí: analyzuje se vstupní sekvence a zjistí se četnost jejich prvků. Výsledkem je v tomto případě slovník (dictionary) jehož klíči jsou prvky ze vstupní sekvence a hodnotami pak jejich četnosti. Podívejme se na jednoduchý příklad se sekvencí tvořenou náhodnými celočíselnými hodnotami. Následně jsou ze sekvence získány unikátní prvky (funkcí unique popsanou dále) a znovu je vypočtena četnost prvků nové sekvence:

from random import randrange
from toolz.itertoolz import frequencies, unique
 
values = [randrange(1, 11, 1) for _ in range(30)]
print(frequencies(values))
 
values2 = unique(values)
print(frequencies(values2))

Na prvním řádku jsou vypsány četnosti prvků z původní sekvence náhodných čísel, na řádku druhém pak četnosti prvků ze sekvence unikátních hodnot:

{8: 6, 6: 3, 3: 2, 2: 4, 4: 3, 10: 2, 9: 5, 7: 2, 1: 2, 5: 1}
{8: 1, 6: 1, 3: 1, 2: 1, 4: 1, 10: 1, 9: 1, 7: 1, 1: 1, 5: 1}

Vše bude pochopitelně funkční i pro sekvence s řetězci či dalšími objekty:

from random import randrange
from toolz.itertoolz import frequencies, unique
 
values = ("Karel", "Ivan", "Petr", "Pavel", "Jan", "Petr", "Ivan", "Ivan")
print(frequencies(values))

Výsledky:

{'Karel': 1, 'Ivan': 3, 'Petr': 2, 'Pavel': 1, 'Jan': 1}

3. Rozdělení sekvence na základě výsledků funkce aplikované na prvky

Již minule jsme si popsali funkci nazvanou partition. Ovšem v balíčku itertoolz nalezneme ještě další dvě funkce s podobným jménem. Jedná se o funkce partitionby a partition_all. Nejprve se podívejme na funkci partitionby, která je taktéž obecně velmi užitečná. Tato funkce sekvenčně prochází vstupní sekvencí a pro každý přečtený prvek volá nějakou uživatelem specifikovanou funkci. Ve chvíli, kdy volaná funkce vrátí odlišnou hodnotu (od předchozího volání) jsou do výstupní sekvence vloženy všechny prvky, pro něž daná uživatelská funkce vrací stejnou hodnotu. Pokud například bude uživatelská funkce testovat, zda je prvek menší než 5, bude výstupní sekvence postupně obsahovat n-tice s prvky většími nebo rovny pěti následované sekvencí s prvky menšími než 5, následované sekvencí s prvky většími nebo rovny pěti atd.

Podívejme se na příklad:

from random import randrange
from toolz.recipes import partitionby
 
values = [randrange(1, 11, 1) for _ in range(30)]
print(values)
 
values2 = partitionby(lambda x: x < 5, values)
print(list(values2))

Tento skript nejdříve vypíše vstupní sekvenci a následně sekvenci rozdělenou na n-tice s prvky většími nebo rovny 5, popř. naopak s prvky menšími než 5:

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

Více viditelné je chování ve chvíli, kdy se prvky rozdělují na sekvenci prvků kladných a záporných:

from random import randrange
from toolz.recipes import partitionby
 
values = [randrange(-5, 5, 1) for _ in range(30)]
print(values)
 
values2 = partitionby(lambda x: x < 0, values)
print(list(values2))

Výsledky:

[-5, -1, -2, -2, 0, -4, 0, 4, -5, -3, -4, -2, -3, -4, 4, -1, 0, -2, 3, -1, -5, -4, -4, 3, -5, -5, -1, 4, 3, -2]
[(-5, -1, -2, -2), (0,), (-4,), (0, 4), (-5, -3, -4, -2, -3, -4), (4,), (-1,), (0,), (-2,), (3,), (-1, -5, -4, -4), (3,), (-5, -5, -1), (4, 3), (-2,)]
Poznámka: toto chování je velmi odlišné od funkce groupby!

4. Rozdělení prvků nekonečné sekvence

Funkce partitionby, podobně jako některé další funkce z knihovny Toolz, dokáže pracovat s nekonečnými sekvencemi. To znamená, že vyhodnocení (výstupní sekvence) je prováděno „líně“ a až ve chvíli, kdy je to skutečně nezbytné. Ostatně si toto chování můžeme relativně snadno otestovat na vstupní sekvenci celočíselných hodnot od 0 do (teoreticky) nekonečna. Pokusíme se tuto sekvenci rozdělit na podsekvence sudých nebo lichých čísel. To je pochopitelně nekonečně dlouhá operace, ovšem nás bude zajímat prvních deset prvků z výsledné sekvence. A ty lze vypočítat v konečném čase:

from toolz.recipes import partitionby
from toolz.itertoolz import iterate, take
 
 
def inc(x):
    return x+1
 
 
values = iterate(inc, 0)
 
values2 = partitionby(lambda x: x % 2 == 0, values)
 
print(list(take(10, values2)))

Výsledkem bude sekvence deseti prvků, přičemž každý prvek bude jednoprvková n-tice (sudost/lichost se mění s každým prvkem na vstupu):

[(0,), (1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,)]

Zajímavější je test na zbytek po dělení pěti:

from toolz.recipes import partitionby
from toolz.itertoolz import iterate, take
 
 
def inc(x):
    return x+1
 
 
values = iterate(inc, 0)
 
values2 = partitionby(lambda x: x % 5 == 4, values)
 
print(list(take(10, values2)))

Nyní bude výsledkem opět sekvence deseti prvků, ovšem nyní každý prvek (jenž je n-ticí) může obsahovat různý počet hodnot:

[(0, 1, 2, 3), (4,), (5, 6, 7, 8), (9,), (10, 11, 12, 13), (14,), (15, 16, 17, 18), (19,), (20, 21, 22, 23), (24,)]

5. Posuvné okno nad sekvencí

Mnohdy je vhodné sekvenci hodnot zpracovávat nikoli po částech (což zajišťuje funkce partition, kterou již známe), ale s využitím posuvného okna. Takové okno nabízí pohled na několik po sobě jdoucích prvků sekvence (například na pět prvků). Další okno nabízí pohled na čtyři původní prvky a jeden prvek nový atd. Prvky se tedy v postupně vytvářené výstupní sekvenci vždy objeví vícekrát, pokaždé na jiném místě okna. Podívejme se na velmi jednoduchý příklad se vstupní sekvencí s deseti prvky a posuvným oknem, které má velikost (rozsah) pěti prvků:

from toolz.itertoolz import sliding_window
 
values = range(10)
 
print(values)
 
for window in sliding_window(5, values):
    print(window)

Posuvné okno nám vytvoří celkem pět pohledů na původní sekvenci s hodnotami 0 až 9:

(0, 1, 2, 3, 4)
(1, 2, 3, 4, 5)
(2, 3, 4, 5, 6)
(3, 4, 5, 6, 7)
(4, 5, 6, 7, 8)
(5, 6, 7, 8, 9)

Okna menší či naopak větší povedou k odlišným výsledkům:

from toolz.itertoolz import sliding_window
 
values = range(10)
 
print(values)
 
for window in sliding_window(3, values):
    print(window)
 
print()
 
for window in sliding_window(7, values):
    print(window)

Pro okno o šířce tří prvků dostaneme tyto výsledky:

(0, 1, 2)
(1, 2, 3)
(2, 3, 4)
(3, 4, 5)
(4, 5, 6)
(5, 6, 7)
(6, 7, 8)
(7, 8, 9)

A toto jsou výsledky pro širší okno, které obsáhne sedm prvků:

(0, 1, 2, 3, 4, 5, 6)
(1, 2, 3, 4, 5, 6, 7)
(2, 3, 4, 5, 6, 7, 8)
(3, 4, 5, 6, 7, 8, 9)

6. Posuvné okno a nekonečná vstupní sekvence

Zajímavé je, že posuvné okno lze vytvořit i pro nekonečnou sekvenci, což si pochopitelně taktéž musíme ukázat. Nad nekonečnou sekvencí celých čísel je vytvořeno okno o šířce pěti prvků, které bude generovat nekonečné množství pětic. Ovšem z těchto pětic si vybereme pouze prvních dvacet:

from toolz.itertoolz import iterate, partition, take, sliding_window
 
 
def inc(x):
    return x+1
 
 
values = iterate(inc, 10)
 
sw = sliding_window(5, values)
 
for window in take(20, sw):
    print(window)

Výsledné pohledy, přesněji řečeno prvních dvacet pohledů na nekonečnou sekvenci vypadají takto:

(10, 11, 12, 13, 14)
(11, 12, 13, 14, 15)
(12, 13, 14, 15, 16)
(13, 14, 15, 16, 17)
(14, 15, 16, 17, 18)
(15, 16, 17, 18, 19)
(16, 17, 18, 19, 20)
(17, 18, 19, 20, 21)
(18, 19, 20, 21, 22)
(19, 20, 21, 22, 23)
(20, 21, 22, 23, 24)
(21, 22, 23, 24, 25)
(22, 23, 24, 25, 26)
(23, 24, 25, 26, 27)
(24, 25, 26, 27, 28)
(25, 26, 27, 28, 29)
(26, 27, 28, 29, 30)
(27, 28, 29, 30, 31)
(28, 29, 30, 31, 32)
(29, 30, 31, 32, 33)

7. Nalezení unikátních prvků v sekvenci

V sekvencích se pochopitelně mohou vyskytovat duplikátní prvky. Ovšem v některých případech vyžadujeme, aby byl každý prvek v sekvenci unikátní. Někdy se tento problém řeší transformací sekvence na množinu a zpět (s problematickým pořadím prvků), ovšem lepší řešení spočívá ve využití funkce unique.

Nejprve vytvoříme sekvenci obsahující všechny znaky abecedy, ovšem opakované třikrát po sobě. Následně z této sekvence odstraníme duplicity, takže by měla vzniknout sekvence unikátních prvků, a to se zachováním jejich pořadí:

from toolz.itertoolz import unique
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)] * 3
 
print(values)
 
values2 = unique(values)
print(list(values2))

Skript nejprve vypíše vstupní sekvenci (abecedu opakovanou třikrát) a posléze sekvenci vypočtenou:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
 
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

Tutéž operaci můžeme pochopitelně provést i pro sekvenci pseudonáhodných celočíselných hodnot:

from random import randrange
from toolz.itertoolz import unique
 
values = [randrange(1, 11, 1) for _ in range(30)]
print(values)
 
values2 = unique(values)
print(list(values2))

Výsledek může vypadat následovně (opět se jedná nejprve o původní sekvenci následovanou sekvencí s odstraněnými duplicitami):

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

8. Test, zda sekvence obsahuje unikátní prvky

S problematikou duplicit či naopak unikátních prvků souvisí i další popisovaná funkce, která se jmenuje isdistinct. Ta slouží k testu, zda sekvence obsahuje pouze unikátní prvky. Pokud je nalezena duplicita, vrací funkce pravdivostní hodnotu False.

Otestujme si chování na sekvenci s duplicitami i na sekvenci s unikátními prvky:

from random import randrange
from toolz.itertoolz import isdistinct, unique
 
values = [randrange(1, 11, 1) for _ in range(30)]
print(list(values))
print(isdistinct(values))
 
print()
 
values2 = unique(values)
print(list(values2))
print(isdistinct(values2))

Výsledky vypsané tímto skriptem mluví samy za sebe, jak by řekl Hans Niemann:

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

9. Rozdíl mezi operací partition a partition_all

Ještě se na chvíli vraťme k operaci partition, o níž jsme se zmínili v předchozím článku. Tato operace dokáže prvky z původní sekvence rozdělit do n-tic se zadanou délkou. Pokud ovšem například budeme chtít prvky rozdělit do trojic a celkový počet prvků nebude dělitelný třemi, poslední jeden až dva prvky budou zahozeny. To lze částečně „napravit“ tak, že specifikujeme i výchozí hodnotu prvků. V takovém případě budou poslední prvky doplněny o další prvky s touto hodnotou tak, aby výsledkem byla sekvence vždy stejně dlouhých n-tic. Funkce partition_all naproti tomu může vrátit poslední n-tici kratší, takže zde nemusíme řešit problém výchozí hodnoty prvků (na druhou stranu je nutné v dalším kódu počítat s tím, že n-tice nebudou mít shodnou délku):

from toolz.itertoolz import partition, partition_all
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print(list(partition(3, values)))
print(list(partition_all(3, values)))

Při pohledu na druhý a třetí řádek je vidět rozdílné chování obou výše zmíněných operací:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
 
[('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'H', 'I'), ('J', 'K', 'L'), ('M', 'N', 'O'), ('P', 'Q', 'R'), ('S', 'T', 'U'), ('V', 'W', 'X')]
[('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'H', 'I'), ('J', 'K', 'L'), ('M', 'N', 'O'), ('P', 'Q', 'R'), ('S', 'T', 'U'), ('V', 'W', 'X'), ('Y', 'Z')]

10. Operace get

V knihovně Toolz nalezneme i operaci get použitelnou na libovolnou kolekci, tedy jak na sekvenci, tak i na slovník. Přitom je možné v jediné operaci get specifikovat větší množství selektorů tak, jak je to ukázáno v dalším příkladu. Taktéž je možné specifikovat hodnotu, která se má vrátit v případě, že kolekce prvek s daným selektorem neobsahuje. Pokud tuto hodnotu nezadáme a prvek není nalezen, vyhodí se výjimka:

from toolz.itertoolz import get
 
phonebook = {"Alice": "555-1234", "Bob": "555-5678", "Charlie": "555-9999"}
 
print(get("Bob", phonebook))
print(get(["Alice", "Bob"], phonebook))
print(get("Zdenek", phonebook, "unknown"))
print(get("Zdenek", phonebook))

A takto vypadají výsledky, včetně výše zmíněné výjimky v posledním případě:

555-5678
('555-1234', '555-5678')
unknown
Traceback (most recent call last):
  File "get.py", line 8, in <module>
    print(get("Zdenek", phonebook))
  File "/home/ptisnovs/.local/lib/python3.8/site-packages/toolz/itertoolz.py", line 454, in get
    return seq[ind]
KeyError: 'Zdenek'

11. Operace pluck

Potenciálně velmi užitečná je operace nazvaná pluck. Jedná se vlastně o operaci get, ovšem postupně aplikovanou na všechny prvky sekvence. To například znamená, že pokud máme sekvenci slovníků a potřebujeme získat pouze hodnoty pod určitým klíčem (ve všech těchto slovnících), lze použít operaci pluck, a to bez nutnosti zápisu programové smyčky. Příklad použití na sekvenci obsahující telefonní čísla tří osob:

from toolz.itertoolz import pluck
 
phonebook = [
    {"id": 0, "name": "Alice",   "phone": "555-1234"},
    {"id": 1, "name": "Bob",     "phone": "555-5678"},
    {"id": 2, "name": "Charlie", "phone": "555-9999"},
]
 
print(list(pluck("id", phonebook)))
print(list(pluck("name", phonebook)))
print(list(pluck("phone", phonebook)))

V prvním případě získáme sekvenci ID, ve druhém případě sekvenci jmen a ve třetím případě sekvenci telefonních čísel:

[0, 1, 2]
['Alice', 'Bob', 'Charlie']
['555-1234', '555-5678', '555-9999']

Podobně jako u get je možné i zde použít více selektorů:

from toolz.itertoolz import pluck

phonebook = [
    {"id": 0, "name": "Alice", "phone": "555-1234"},
    {"id": 1, "name": "Bob", "phone": "555-5678"},
    {"id": 2, "name": "Charlie", "phone": "555-9999"},
]
 
print(list(pluck(["name", "phone"], phonebook)))

Tentokrát s výsledky:

[('Alice', '555-1234'), ('Bob', '555-5678'), ('Charlie', '555-9999')]

12. Spojení sekvencí na základě klíčů (join)

Už předchozí operace pluck do jisté míry připomíná příkaz query z SQL (či jiného dotazovacího jazyka). Knihovna Toolz nabízí programátorům i další „databázovou“ operaci. Jedná se o operaci spojení (join) realizovanou funkcí se stejným jménem, tedy join. Této funkci musíme předat dvojici sekvencí, které se mají spojit. Navíc je nutné předat i selektory prvků z první i ze druhé sekvence. Tyto selektory jsou použity podobně, jako v operaci pluck a pokud se v první i druhé sekvenci naleznou totožné vybrané hodnoty, jsou tyto prvky spojeny a vloženy do výsledné sekvence.

Podívejme se na příklad dvou sekvencí (konkrétně sekvencí n-tic), které chceme spojit přes jména. V první sekvenci jsou jména uložena ve druhých prvcích n-tic (tedy pod indexem 1), ve druhé sekvenci pak na začátku každé n-tice (tedy s indexem 0). Spojení se tedy provede operací join(1, names, 0, phones):

from toolz.itertoolz import join
 
names = [
    (0, "Alice"),
    (1, "Bob"),
    (2, "Charlie"),
]
 
phones = [
    ("Alice",   "555-1234"),
    ("Bob",     "555-5678"),
    ("Charlie", "555-9999"),
]
 
for item in join(1, names, 0, phones):
    print(item)

Výsledkem bude sekvence dvojic obsahujících původní prvky:

((0, 'Alice'), ('Alice', '555-1234'))
((1, 'Bob'), ('Bob', '555-5678'))
((2, 'Charlie'), ('Charlie', '555-9999'))
Poznámka: pokuste se prvky první nebo druhé sekvence prohodit. V každém případě bude spojení funkční, i když se může změnit pořadí jmen na výstupu.

13. Vylepšení tisku výsledku operace join

Vzhledem k tomu, v jakém formátu jsou získány výsledky operace join, se pokusme vylepšit tisk tabulky se jmény a telefonními čísly. Výslednou sekvenci vytiskneme tak, že z každého jejího prvku (což je dvojice) přečteme jen ty hodnoty, které budeme chtít vytisknout. Například pro tento prvek z výsledné sekvence:

((1, 'Bob'), ('Bob', '555-5678'))

získáme první prvek z první n-tice (ID), druhý prvek z první n-tice (jméno) a druhý prvek ze druhé n-tice (telefonní číslo):

print(item[0][0], item[0][1], item[1][1])

Upravený skript bude vypadat následovně:

from toolz.itertoolz import join
 
names = [
    (0, "Alice"),
    (1, "Bob"),
    (2, "Charlie"),
]
 
phones = [
    ("Alice",   "555-1234"),
    ("Bob",     "555-5678"),
    ("Charlie", "555-9999"),
]
 
for item in join(1, names, 0, phones):
    print(item[0][0], item[0][1], item[1][1])

A takto bude vypadat vytištěný telefonní seznam:

0 Alice 555-1234
1 Bob 555-5678
2 Charlie 555-9999

14. Vnitřní spojení (inner join)

Ve skutečnosti je výchozím typem spojení vnitřní spojení neboli inner join. To si ostatně můžeme velmi snadno ukázat na dalším demonstračním příkladu, v němž spojujeme dvojici sekvencí přes „sloupce“ se jmény („Alice“, „Bob“ atd.). Ovšem povšimněte si, že v první sekvenci je jeden záznam, který nelze spojit se záznamem ve druhé sekvenci („Zdenek“). A naopak, i ve druhé sekvenci je záznam, jenž nemá svůj protějšek v první sekvenci („Martin“). Vnitřní spojení v podstatě tyto záznamy bude ignorovat:

from toolz.itertoolz import join
 
names = [
    (0, "Alice"),
    (1, "Bob"),
    (2, "Charlie"),
    (3, "Zdenek"),
]
 
phones = [
    ("Alice",   "555-1234"),
    ("Bob",     "555-5678"),
    ("Charlie", "555-9999"),
    ("Martin",  "000-0000"),
]
 
for item in join(1, names, 0, phones):
    print(item[0][0], item[0][1], item[1][1])

Výsledkem vnitřního spojení je skutečně jen sekvence se třemi záznamy, které vznikly propojením obou vstupních sekvencí přes sloupce se jmény:

0 Alice 555-1234
1 Bob 555-5678
2 Charlie 555-9999

15. Vnější spojení (outer join)

Funkce join umožňuje navíc realizovat i spojení zleva, spojení zprava i plné vnější spojení (left join, right join, outer join). Podívejme se nejdříve na spojení zleva, které je provedeno po nastavení nepovinného parametru nazvaného left_default, který slouží pro „doplnění“ hodnot v první sekvenci:

from toolz.itertoolz import join
 
names = [
    (0, "Alice"),
    (1, "Bob"),
    (2, "Charlie"),
    (3, "Zdenek"),
]
 
phones = [
    ("Alice",   "555-1234"),
    ("Bob",     "555-5678"),
    ("Charlie", "555-9999"),
    ("Martin",  "000-0000"),
]
 
for item in join(1, names, 0, phones, left_default=(0, "Nikdo")):
    print(item[0][0], item[0][1], item[1][0], item[1][1])

Výsledkem bude telefonní seznam se čtyřmi záznamy:

0 Alice Alice 555-1234
1 Bob Bob 555-5678
2 Charlie Charlie 555-9999
0 Nikdo Martin 000-0000

V případě, že specifikujeme „doplňované“ hodnoty jak pro první vstupní sekvenci (left_default), tak i pro sekvenci druhou (right_default), je provedeno plné vnější spojení neboli outer join. Opět se podívejme na příklad s dvojicí vstupních sekvencí, v nichž některé prvky nemají protějšek ve druhé sekvenci:

from toolz.itertoolz import join
 
names = [
    (0, "Alice"),
    (1, "Bob"),
    (2, "Charlie"),
    (3, "Zdenek"),
]
 
phones = [
    ("Alice",   "555-1234"),
    ("Bob",     "555-5678"),
    ("Charlie", "555-9999"),
    ("Martin",  "000-0000"),
]
 
for item in join(1, names, 0, phones, left_default=(0, "Nikdo"), right_default=("Neznamy", "111-1111")):
    print(item[0][0], item[0][1], item[1][0], item[1][1])

Nyní bude výsledkem pět řádků, protože pro chybějící protějšky se automaticky doplnila výchozí hodnota:

hacking_tip

0 Alice Alice 555-1234
1 Bob Bob 555-5678
2 Charlie Charlie 555-9999
0 Nikdo Martin 000-0000
3 Zdenek Neznamy 111-1111

16. Obsah navazujícího článku

Ve třetím článku o funkcionální knihovně Toolz již opustíme funkce určené pro zpracování sekvencí. Namísto toho se zaměříme na mnohem zajímavější oblast, konkrétně na transformaci funkcí, currying, částečné vyhodnocení funkcí atd. Tedy na techniky, které jsme mohli vidět (i když v jiné podobě) i v knihovně funcy. Toolz ovšem nabízí ucelenější a dobře propojené API k těmto technikám.

17. Repositář s demonstračními příklady

Všechny Pythonovské skripty, které jsme si prozatím v tomto seriálu ukázali, naleznete na adrese https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady (pro jejich spuštění je nutné mít nainstalovánu některou z podporovaných verzí Pythonu 3, a pro dnešní příklady i výše zmíněnou knihovnu funcy):

# Příklad Stručný popis Adresa
1 binary_operator.py ukázka funkce vyššího řádu, která jako parametr akceptuje jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/binary_operator.py
2 get_operator1.py ukázka funkce vyššího řádu, která vrací jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator1.py
3 get_operator2.py ukázka funkce vyššího řádu, která vrací jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator2.py
4 standard_operators.py použití standardních operátorů přepsaných do formy funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/standard_operators.py
       
5 binary_operator_types.py varianta příkladu binary_operator.py s plnými typovými deklaracemi https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/binary_operator_types.py
6 get_operator_types.py varianta příkladu get_operator2.py s plnými typovými deklaracemi https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator_types.py
       
7 map1.py příklad použití funkce map: výpočet délky všech slov v textu https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map1.py
8 map2.py příklad použití funkce map: výpočet absolutní hodnoty všech členů posloupnosti https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map2.py
9 map3.py příklad použití funkce map: aplikace vlastní pojmenované funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map3.py
10 map4.py příklad použití funkce map: aplikace vlastního lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map4.py
       
11 map_list_comprehension1.py přepis skriptu map1.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
12 map_list_comprehension2.py přepis skriptu map2.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
13 map_list_comprehension3.py přepis skriptu map3.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
14 map_list_comprehension4.py přepis skriptu map4.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
       
15 filter1.py filtrace dat na základě délky řetězce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter1.py
16 filter2.py filtrace numerických dat podle toho, zda se jedná o sudá či lichá čísla https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter2.py
17 filter3.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter3.py
       
18 filter_list_comprehension1.py přepis skriptu filter_list_comprehension1.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on1.py
19 filter_list_comprehension2.py přepis skriptu filter_list_comprehension2.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on2.py
20 filter_list_comprehension3.py přepis skriptu filter_list_comprehension3.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on3.py
       
21 reduce1.py výpočet faktoriálu s využitím funkce vyššího řádu reduce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce1.py
22 reduce2.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce2.py
23 reduce3.py tisk tabulky faktoriálů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce3.py
24 reduce4.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce4.py
25 reduce5.py přepis předchozího příkladu s využitím generátorové notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce5.py
       
26 return_function.py funkce jako návratová hodnota jiné funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/return_function.py
27 closure_adder1.py příklad použití uzávěru – konstrukce funkce typu adder https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/closure_adder1.py
28 counter_closure1.py nekorektní implementace čítače s využitím uzávěrů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure1.py
29 counter_closure2.py přístup k nelokálnímu symbolu (Python 2.x i Python 3.x) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure2.py
30 counter_closure3.py přístup k nelokálnímu symbolu (pouze Python 3.x) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure3.py
       
31 access_nonlocal_symbol.py přístup k nelokálnímu symbolu v uzávěru https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/access_nonlocal_symbol.py
32 functions_and_closures.py funkce a uzávěry (umělý příklad) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/functions_and_closures.py
       
33 partial1.py funkce doubler odvozená (redukcí) z univerzálnější funkce mul https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial1.py
34 partial2.py transformace funkce se třemi parametry s využitím partial (nekorektní řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial2.py
35 partial3.py transformace funkce se třemi parametry s využitím partial (korektní řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial3.py
36 partial4.py transformace funkce s dosazením většího množství parametrů s využitím partial https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial4.py
37 partial5.py několikanásobná transformace původní funkce na několik nových funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial5.py
38 partial6.py postupná transformace již ztransformovaných funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial6.py
39 partial7.py typ originální funkce i funkcí získaných s využitím transformace pomocí partial https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial7.py
40 partial8.py jméno funkce, poziční argumenty funkce a pojmenované argumenty funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial8.py
41 partial9.py transformace reduce a pojmenované argumenty původní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial9.py
42 partial_A.py získání informací o redukované funkci s pojmenovanými argumenty https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_A.py
       
43 partial_method1.py třída s metodou s parametry https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method1.py
44 partial_method2.py třída s metodou s parametry – vliv volání setteru na stav objektu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method2.py
45 partial_method3.py metody enable a disable vzniklé transformací set_enabled https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method3.py
46 partial_method4.py další příklad použití funkce partialmethod – doplnění většího množství parametrů při transformaci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method4.py
       
47 lru_cache1.py klasický výpočet Fibonacciho posloupnosti rekurzivní funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache1.py
48 lru_cache2.py LRU cache pro výsledky Fibonacciho posloupnosti pro nejčastěji použité vstupy https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache2.py
49 lru_cache3.py přečtení informací o využití LRU cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache3.py
50 lru_cache4.py programové vymazání LRU cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache4.py
       
51 cached_property1.py použití standardního dekorátoru @property https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property1.py
52 cached_property2.py použití dekorátoru @cached_property https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property2.py
53 cached_property3.py úprava předchozího příkladu tak, aby se využila LRU cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property3.py
       
54 total_ordering.py příklad implementace relačních operátorů založených na dekorátoru @total_ordering https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/total_ordering.py
       
55 decorators2.py příklad použití jednoho dekorátoru aplikovaného na funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators2.py
56 decorators3.py příklad použití dvou dekorátorů aplikovaných na funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators3.py
57 measure_time.py praktické použití dekorátoru – měření doby trvání funkce označené dekorátorem https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/measure_time.py
       
58 decorators4.py atributy transformované funkce vytvořené s využitím dekorátoru https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators4.py
59 decorators5.py využití dekorátoru @wraps pro automatickou úpravu atributů „obalované“ funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators5.py
60 decorators6.py dekorátor @wraps a několikanásobná aplikace dekorátorů na „obalovanou“ funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators6.py
       
61 decorators1.py zkrácená deklarace dekorátoru s využitím dekorátoru @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/de­corators1.py
62 decorators2.py několikanásobná aplikace dekorátorů, dekorátor je vytvořen přes @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/de­corators2.py
63 measure_time.py měření doby trvání funkce označené dekorátorem, dekorátor je vytvořen přes @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/measure_time.py
       
64 curry1.py curryfikace funkce se dvěma parametry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/curry1.py
65 curry2.py curryfikace funkce se třemi parametry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/curry2.py
66 rcurry1.py curryfikace funkce div funkcí curry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry1.py
67 rcurry2.py curryfikace funkce div funkcí rcurry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry2.py
68 rcurry3.py curryfikace funkce n_pow funkcí rcurry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry3.py
       
69 autocurry.py curryfikace funkce n_pow funkcí autocurry (s odlišným výsledkem) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/autocurry.py
       
70 compose1.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose1.py
71 compose2.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose2.py
72 compose3.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose3.py
73 rcompose1.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose1.py
74 rcompose2.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose2.py
75 rcompose3.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose3.py
       
76 filter1.py použití standardní funkce filter (opakování) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter1.py
77 filter2.py použití funkce filter z knihovny funcy https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter2.py
78 filter3.py funkce vyššího řádu lfilter https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter3.py
79 filter4.py předání lambda výrazu do funkcí vyššího řádu filter a lfilter https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter4.py
80 filter5.py regulární výraz ve funkci predikátu https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter5.py
81 filter6.py množina ve funkci predikátu https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter6.py
82 filter7.py množina ve funkci predikátu https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter7.py
       
83 remove1.py použití funkce vyššího řádu remove https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove1.py
84 remove2.py použití funkce vyššího řádu lremove https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove2.py
85 remove3.py kombinace regulárního výrazu a funkce vyššího řádku lremove https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove3.py
86 remove4.py kombinace množin a funkce vyššího řádku lremove https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove4.py
       
87 map1.py použití standardní funkce map (opakování) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map1.py
88 map2.py použití funkce map z knihovny funcy https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map2.py
89 map3.py funkce vyššího řádu lmap https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map3.py
90 map4.py použití regulárního výrazu namísto transformační funkce v lmap https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map4.py
91 map5.py použití regulárního výrazu namísto transformační funkce v lmap https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map5.py
       
92 distinct1.py získání unikátních prvků ze vstupní sekvence funkcí distinct https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/distinct1.py
93 distinct2.py získání unikátních prvků ze vstupní sekvence funkcí distinct https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/distinct2.py
       
94 take_while1.py filtrace prvků sekvence funkcí takewhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ta­ke_while1.py
95 take_while2.py filtrace prvků sekvence funkcí takewhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ta­ke_while2.py
96 drop_while1.py filtrace prvků sekvence funkcí dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/drop_whi­le1.py
97 drop_while2.py filtrace prvků sekvence funkcí dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/drop_whi­le2.py
       
98 split1.py rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split1.py
99 split2.py rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split2.py
100 split3.py rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split3.py
101 split4.py rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split4.py
       
102 split_by1.py kombinace funkcí vyššího řádu takewhile a dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split_by1.py
103 split_by2.py kombinace funkcí vyššího řádu takewhile a dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split_by2.py
       
104 partition_by.py rozdělení sekvence na větší množství sekvencí funkcí partition_by https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/partition_by.py
       
105 count1.py nekonečná sekvence čítačů s hodnotami 0, 1, 2, … https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count1.py
106 count2.py získání prvních dvaceti hodnot čítačů z původně nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count2.py
107 count3.py kombinace konečné a nekonečné sekvence s využitím standardní funkce zip https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count3.py
108 count4.py kombinace dvou nekonečných sekvencí s využitím standardní funkce zip https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count4.py
109 count5.py specifikace počáteční hodnoty nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count5.py
110 count6.py specifikace počáteční hodnoty a kroku nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count6.py
111 count7.py specifikace záporného kroku nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count7.py
112 count8.py neceločíselný krok i hodnota prvního prvku https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count8.py
       
112 cycle1.py opakující se nekonečná sekvence dvou hodnot https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/cycle1.py
113 cycle2.py opakující se nekonečná sekvence dvou hodnot https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/cycle2.py
114 cycle3.py kombinace dvou opakujících se nekonečných sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/cycle3.py
115 cycle4.py sekvence obsahující označení všech hracích karet https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/cycle4.py
       
116 group_by1.py rozdělení numerických hodnot do deseti skupin https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/group_by1.py
117 group_by2.py rozdělení slov do skupin podle délky https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/group_by2.py
118 group_by3.py rozdělení slov do skupin podle délky, výsledek je seřazen https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/group_by3.py
       
119 iterate1.py sekvence tvořená aritmetickou řadou https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate1.py
120 iterate2.py sekvence tvořená aritmetickou řadou https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate2.py
121 iterate3.py sekvence s celočíselnými mocninami dvojky https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate3.py
122 iterate4.py vygenerování Fibonacciho posloupnosti (neúplné řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate4.py
123 iterate5.py vygenerování Fibonacciho posloupnosti (úplné řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate5.py
       
124 repeat1.py vygenerování konečné sekvence s deseti prvky https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat1.py
125 repeat2.py vygenerování konečné sekvence s deseti prvky, převod sekvence na seznam https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat2.py
126 repeat3.py vygenerování nekonečné sekvence bez její materializace https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat3.py
127 repeat4.py vygenerování nekonečné sekvence s pokusem o její materializaci https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat4.py
128 repeat5.py získání několika prvků z původně nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat5.py
129 repeat6.py kombinace konečné a nekonečné sekvence s využitím standardní funkce zip https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat6.py
       
130 interleave.py kombinace prvků dvou nekonečných sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/interleave.py
       
131 silent1.py výpočet podílu, funkce může vyhodit výjimku https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent1.py
132 silent2.py výpočet podílu, výjimka je zachycena přes @silent https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent2.py
133 silent3.py čtení ze souboru, funkce může vyhodit výjimku https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent3.py
134 silent4.py čtení ze souboru, výjimka je zachycena přes @silent https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent4.py
135 silent5.py explicitní vyhození výjimky s využitím raise https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent5.py
136 silent6.py explicitní vyhození výjimky s využitím raise, zachycení přes @silent https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent6.py
137 silent7.py explicitní vyhození výjimky ve volané funkci, opět zachycení přes @silent https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent7.py
       
138 ignore1.py zachycení výjimky typu Exception a od ní odvozených výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore1.py
139 ignore2.py pokus o zachycení odlišné výjimky, než je ZeroDivisionError https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore2.py
140 ignore3.py zachycení pouze jediné výjimky, která nás při výpočtu zajímá, tedy výjimky vyhození při dělení nulou https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore3.py
141 ignore4.py vrácení zvolené hodnoty v případě, že je výjimka zachycena https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore4.py
142 ignore5.py zachycení výjimky ZeroDivisionError, ignorace výjimky TypeError https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore5.py
143 ignore6.py zachycení výjimky ZeroDivisionError a/nebo TypeError https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore6.py
144 ignore7.py vrácení odlišných hodnot pro různé typy výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore7.py
       
145 reraise1.py základní způsob použití dekorátoru @reraise https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise1.py
146 reraise2.py reakce na odlišný typ výjimky https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise2.py
147 reraise3.py reakce na větší množství typů výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise3.py
148 reraise4.py použití @reraise, ovšem s prázdným parametrem errors https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise4.py
149 reraise5.py využití informací z původní výjimky v nové výjimce https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise5.py
       
150 retry1.py základní způsob použití dekorátoru @retry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry1.py
151 retry2.py specifikace parametru timeout https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry2.py
152 retry3.py specifikace typu zachytávaných výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry3.py
153 retry4.py specifikace typu zachytávaných výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry4.py
154 retry5.py exponenciálně vzrůstající hodnota timeout https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry5.py
       
       
155 seq_first.py test operace first pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_first.py
156 seq_last.py test operace last pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_last.py
157 seq_take.py test operace take pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_take.py
158 seq_drop.py test operace drop pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_drop.py
159 seq_nth.py test operace nth pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_nth.py
160 seq_get.py test operace get pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_get.py
       
161 iterate1.py sekvence tvořená aritmetickou řadou, použití pojmenované funkce https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate1.py
162 iterate2.py sekvence tvořená aritmetickou řadou, použití anonymní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate2.py
163 iterate3.py sekvence s celočíselnými mocninami dvojky https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate3.py
164 iterate4.py vygenerování Fibonacciho posloupnosti (neúplné řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate4.py
165 iterate5.py vygenerování Fibonacciho posloupnosti (úplné řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate5.py
166 iterate6.py vygenerování seznamů s aritmetickými řadami https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate6.py
167 accumulate.py postupná redukce vstupu s akumulací mezivýsledků https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/accumulate.py
168 diff1.py výpočet rozdílu mezi dvěma sekvencemi https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/diff1.py
169 diff2.py výpočet rozdílu mezi třemi sekvencemi https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/diff2.py
170 group_by1.py operace groupby: rozdělení numerických hodnot do deseti skupin https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/group_by1.py
171 group_by2.py rozdělení slov do skupin podle délky https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/group_by2.py
172 group_by3.py rozdělení slov do skupin podle délky, výsledek je navíc seřazen https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/group_by3.py
173 group_by_infinite.py operace groupby nad nekonečnou sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/grou­p_by_infinite.py
174 interleave.py kombinace většího množství sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/interleave.py
175 interleave_length.py délka výsledné sekvence získaná po spojení sekvencí různé délky https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/in­terleave_length.py
176 interleave_infinite.py kombinace nekonečných sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/in­terleave_infinite.py
177 interpose.py proložení prvků sekvence další hodnotou https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/interpose.py
178 partition.py rozdělení prvků sekvence do většího množství sekvencí pomocí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/partition.py
179 partition_infinite.py rozdělení nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/par­tition_infinite.py
180 reduce.py varianta funkce reduce https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/reduce.py
181 parallel_fold.py paralelní varianta funkce reduce https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/pa­rallel_fold.py
       
182 frequencies.py získání četnosti prvků v sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/frequencies.py
183 interpose_infinite.py operace interpose a nekonečná sekvence na vstupu https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/in­terpose_infinite.py
184 isdistinct.py test, zda sekvence obsahuje unikátní prvky https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/isdistinct.py
185 partitionby1.py rozdělení prvků sekvence na základě výsledků funkce pro každý prvek https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/partitionby1.py
186 partitionby2.py dtto, ale s odlišnou funkcí a vstupem https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/partitionby2.py
187 partitionby_infinite.py rozdělení prvků nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/par­titionby_infinite.py
188 partitionby_infinite2.py rozdělení prvků nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/par­titionby_infinite2.py
189 sliding_window1.py posuvné okno nad sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/sli­ding_window1.py
190 sliding_window2.py dtto, ale pro odlišné parametry https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/sli­ding_window2.py
191 sliding_window_infinite.py posuvné okno a nekonečná vstupní sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/sli­ding_window_infinite.py
192 unique1.py nalezení unikátních prvků v sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/unique1.py
193 unique2.py dtto, ale pro odlišné parametry https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/unique2.py
194 partition_all.py operace partition_all https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/par­tition_all.py
195 get.py operace get https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/get.py
196 pluck.py operace pluck https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/pluck.py
197 join1.py operace join, základní způsob použití https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join1.py
198 join2.py operace join, výběr ze spojených prvků https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join2.py
199 join3.py operace inner join https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join3.py
200 join4.py operace outer join https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join4.py
201 join5.py operace outer join https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join5.py

18. Odkazy na Internetu

  1. Getting started with functional programming in Python using the toolz library
    https://opensource.com/ar­ticle/18/10/functional-programming-python-toolz
  2. Toolz module in Python
    https://www.geeksforgeeks.org/toolz-module-in-python/
  3. functools — Higher-order functions and operations on callable objects
    https://docs.python.org/3/li­brary/functools.html
  4. Functional Programming HOWTO
    https://docs.python.org/3/how­to/functional.html
  5. Functional Programming in Python: When and How to Use It
    https://realpython.com/python-functional-programming/
  6. Functional Programming With Python
    https://realpython.com/learning-paths/functional-programming/
  7. Awesome Functional Python
    https://github.com/sfermigier/awesome-functional-python
  8. Currying
    https://en.wikipedia.org/wi­ki/Currying
  9. Currying in Python – A Beginner’s Introduction
    https://www.askpython.com/pyt­hon/examples/currying-in-python
  10. Fundamental Concepts in Programming Languages
    https://en.wikipedia.org/wi­ki/Fundamental_Concepts_in_Pro­gramming_Languages
  11. When should I use function currying?
    https://stackoverflow.com/qu­estions/24881604/when-should-i-use-function-currying
  12. Toolz
    https://github.com/pytool­z/toolz/tree/master
  13. Coconut: funkcionální jazyk s pattern matchingem kompatibilní s Pythonem
    https://www.root.cz/clanky/coconut-funkcionalni-jazyk-s-pattern-matchingem-kompatibilni-s-pythonem/
  14. A HITCHHIKER'S GUIDE TO functools
    https://ep2021.europython­.eu/media/conference/slides/a-hitchhikers-guide-to-functools.pdf
  15. Coconut aneb funkcionální nadstavba nad Pythonem (2.část)
    https://www.root.cz/clanky/coconut-aneb-funkcionalni-nadstavba-nad-pythonem-2-cast/
  16. Knihovny pro zpracování posloupností (sekvencí) v Pythonu
    https://www.root.cz/clanky/knihovny-pro-zpracovani-posloupnosti-sekvenci-v-pythonu/
  17. clj – repositář s knihovnou
    https://github.com/bfontaine/clj
  18. clj 0.1.0 – stránka na PyPi
    https://pypi.python.org/py­pi/clj/0.1.0
  19. Clojure aneb jazyk umožňující tvorbu bezpečných vícevláknových aplikací pro JVM (4.část – kolekce, sekvence a lazy sekvence)
    https://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-4-cast-kolekce-sekvence-a-lazy-sekvence/
  20. Clojure a bezpečné aplikace pro JVM: sekvence, lazy sekvence a paralelní programy
    https://www.root.cz/clanky/clojure-a-bezpecne-aplikace-pro-jvm-sekvence-lazy-sekvence-a-paralelni-programy/
  21. Coconut: Simple, elegant, Pythonic functional programming
    http://coconut-lang.org/
  22. coconut (Python package index)
    https://pypi.python.org/pypi/coconut/
  23. Coconut Tutorial
    http://coconut.readthedoc­s.io/en/master/HELP.html
  24. Coconut FAQ
    http://coconut.readthedoc­s.io/en/master/FAQ.html
  25. Coconut Documentation
    http://coconut.readthedoc­s.io/en/master/DOCS.html
  26. Coconut na Redditu
    https://www.reddit.com/r/Pyt­hon/comments/4owzu7/coconut_fun­ctional_programming_in_pyt­hon/
  27. Repositář na GitHubu
    https://github.com/evhub/coconut
  28. Object-Oriented Programming — The Trillion Dollar Disaster
    https://betterprogramming.pub/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7
  29. Goodbye, Object Oriented Programming
    https://cscalfani.medium.com/goodbye-object-oriented-programming-a59cda4c0e53
  30. So You Want to be a Functional Programmer (Part 1)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-1–1f15e387e536
  31. So You Want to be a Functional Programmer (Part 2)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-2–7005682cec4a
  32. So You Want to be a Functional Programmer (Part 3)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-3–1b0fd14eb1a7
  33. So You Want to be a Functional Programmer (Part 4)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-4–18fbe3ea9e49
  34. So You Want to be a Functional Programmer (Part 5)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-5-c70adc9cf56a
  35. So You Want to be a Functional Programmer (Part 6)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-6-db502830403
  36. Why Programmers Need Limits
    https://cscalfani.medium.com/why-programmers-need-limits-3d96e1a0a6db
  37. Infographic showing code complexity vs developer experience
    https://twitter.com/rossi­pedia/status/1580639227313676288
  38. Python's reduce(): From Functional to Pythonic Style
    https://realpython.com/python-reduce-function/
  39. What is the problem with reduce()?
    https://stackoverflow.com/qu­estions/181543/what-is-the-problem-with-reduce
  40. The fate of reduce() in Python 3000
    https://www.artima.com/we­blogs/viewpost.jsp?thread=98196
  41. Reading 16: Map, Filter, Reduce
    http://web.mit.edu/6.031/www/sp22/clas­ses/16-map-filter-reduce/
  42. Currying
    https://sw-samuraj.cz/2011/02/currying/
  43. Používání funkcí v F#
    https://docs.microsoft.com/cs-cz/dotnet/fsharp/tutorials/using-functions
  44. Funkce vyššího řádu
    http://naucte-se.haskell.cz/funkce-vyssiho-radu
  45. Currying (Wikipedia)
    https://en.wikipedia.org/wi­ki/Currying
  46. Currying (Haskell wiki)
    https://wiki.haskell.org/Currying
  47. Haskell Curry
    https://en.wikipedia.org/wi­ki/Haskell_Curry
  48. Moses Schönfinkel
    https://en.wikipedia.org/wi­ki/Moses_Sch%C3%B6nfinkel
  49. ML – funkcionální jazyk s revolučním typovým systémem
    https://www.root.cz/clanky/ml-funkcionalni-jazyk-s-revolucnim-typovym-systemem/
  50. Funkce a typový systém programovacího jazyka ML
    https://www.root.cz/clanky/funkce-a-typovy-system-programovaciho-jazyka-ml/
  51. Curryfikace (currying), výjimky a vlastní operátory v jazyku ML
    https://www.root.cz/clanky/curryfikace-currying-vyjimky-a-vlastni-operatory-v-jazyku-ml/
  52. Primer on Python Decorators
    https://realpython.com/primer-on-python-decorators/
  53. Python Decorators
    https://www.programiz.com/python-programming/decorator
  54. PythonDecorators (Python Wiki)
    https://wiki.python.org/mo­in/PythonDecorators
  55. Funcy na GitHubu
    https://github.com/suor/funcy/
  56. Welcome to funcy documentation!
    https://funcy.readthedocs­.io/en/stable/
  57. Funcy cheatsheet
    https://funcy.readthedocs­.io/en/stable/cheatsheet.html
  58. PyToolz API Documentation
    https://toolz.readthedocs­.io/en/latest/index.html
  59. Toolz (PyToolz) na GitHubu
    https://github.com/pytoolz/toolz
  60. Fn.py: enjoy FP in Python
    https://github.com/kachayev/fn.py
  61. Funcy na PyPi
    https://pypi.org/project/funcy/
  62. Underscore aneb další knihovna pro funkcionální programování v JavaScriptu
    https://www.root.cz/clanky/underscore-aneb-dalsi-knihovna-pro-funkcionalni-programovani-v-javascriptu/
  63. Funkce vyššího řádu v knihovně Underscore
    https://www.root.cz/clanky/funkce-vyssiho-radu-v-knihovne-underscore/
  64. Awesome functional Python
    https://github.com/sfermigier/awesome-functional-python
  65. lispy
    https://pypi.org/project/lispy/
  66. clojure_py na indexu PyPi
    https://pypi.python.org/py­pi/clojure_py
  67. PyClojure
    https://github.com/eigenhom­bre/PyClojure
  68. Hy na GitHubu
    https://github.com/hylang/hy
  69. Hy: The survival guide
    https://notes.pault.ag/hy-survival-guide/
  70. Hy běžící na monitoru terminálu společnosti Symbolics
    http://try-hy.appspot.com/
  71. Welcome to Hy’s documentation!
    http://docs.hylang.org/en/stable/
  72. Hy na PyPi
    https://pypi.org/project/hy/#des­cription
  73. Getting Hy on Python
    https://lwn.net/Articles/596626/
Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.