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:
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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/map_list_comprehension1.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/functools/map_list_comprehension2.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/functools/map_list_comprehension3.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/functools/map_list_comprehension4.py |
|
|
|
|
15 |
filter1.py |
filtrace dat na základě délky řetězce |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/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/functools/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/functools/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/functools/filter_list_comprehension1.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/functools/filter_list_comprehension2.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/functools/filter_list_comprehension3.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/functools/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/functools/reduce2.py |
23 |
reduce3.py |
tisk tabulky faktoriálů |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/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/functools/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/functools/reduce5.py |
|
|
|
|
26 |
return_function.py |
funkce jako návratová hodnota jiné funkce |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/partial5.py |
38 |
partial6.py |
postupná transformace již ztransformovaných funkcí |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/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/functools/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/functools/partial8.py |
41 |
partial9.py |
transformace reduce a pojmenované argumenty původní funkce |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/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/functools/partial_A.py |
|
|
|
|
43 |
partial_method1.py |
třída s metodou s parametry |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/lru_cache3.py |
50 |
lru_cache4.py |
programové vymazání LRU cache |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/lru_cache4.py |
|
|
|
|
51 |
cached_property1.py |
použití standardního dekorátoru @property |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/cached_property1.py |
52 |
cached_property2.py |
použití dekorátoru @cached_property |
https://github.com/tisnik/most-popular-python-libs/blob/master/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/functools/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/decorators1.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/decorators2.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/take_while1.py |
95 |
take_while2.py |
filtrace prvků sekvence funkcí takewhile |
https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/take_while2.py |
96 |
drop_while1.py |
filtrace prvků sekvence funkcí dropwhile |
https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/drop_while1.py |
97 |
drop_while2.py |
filtrace prvků sekvence funkcí dropwhile |
https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/drop_while2.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/group_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/interleave_length.py |
176 |
interleave_infinite.py |
kombinace nekonečných sekvencí |
https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/interleave_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/partition_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/parallel_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/interpose_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/partitionby_infinite.py |
188 |
partitionby_infinite2.py |
rozdělení prvků nekonečné sekvence |
https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/partitionby_infinite2.py |
189 |
sliding_window1.py |
posuvné okno nad sekvencí |
https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/sliding_window1.py |
190 |
sliding_window2.py |
dtto, ale pro odlišné parametry |
https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/sliding_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/sliding_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/partition_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
- Getting started with functional programming in Python using the toolz library
https://opensource.com/article/18/10/functional-programming-python-toolz
- Toolz module in Python
https://www.geeksforgeeks.org/toolz-module-in-python/
- functools — Higher-order functions and operations on callable objects
https://docs.python.org/3/library/functools.html
- Functional Programming HOWTO
https://docs.python.org/3/howto/functional.html
- Functional Programming in Python: When and How to Use It
https://realpython.com/python-functional-programming/
- Functional Programming With Python
https://realpython.com/learning-paths/functional-programming/
- Awesome Functional Python
https://github.com/sfermigier/awesome-functional-python
- Currying
https://en.wikipedia.org/wiki/Currying
- Currying in Python – A Beginner’s Introduction
https://www.askpython.com/python/examples/currying-in-python
- Fundamental Concepts in Programming Languages
https://en.wikipedia.org/wiki/Fundamental_Concepts_in_Programming_Languages
- When should I use function currying?
https://stackoverflow.com/questions/24881604/when-should-i-use-function-currying
- Toolz
https://github.com/pytoolz/toolz/tree/master
- Coconut: funkcionální jazyk s pattern matchingem kompatibilní s Pythonem
https://www.root.cz/clanky/coconut-funkcionalni-jazyk-s-pattern-matchingem-kompatibilni-s-pythonem/
- A HITCHHIKER'S GUIDE TO functools
https://ep2021.europython.eu/media/conference/slides/a-hitchhikers-guide-to-functools.pdf
- Coconut aneb funkcionální nadstavba nad Pythonem (2.část)
https://www.root.cz/clanky/coconut-aneb-funkcionalni-nadstavba-nad-pythonem-2-cast/
- Knihovny pro zpracování posloupností (sekvencí) v Pythonu
https://www.root.cz/clanky/knihovny-pro-zpracovani-posloupnosti-sekvenci-v-pythonu/
- clj – repositář s knihovnou
https://github.com/bfontaine/clj
- clj 0.1.0 – stránka na PyPi
https://pypi.python.org/pypi/clj/0.1.0
- 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/
- 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/
- Coconut: Simple, elegant, Pythonic functional programming
http://coconut-lang.org/
- coconut (Python package index)
https://pypi.python.org/pypi/coconut/
- Coconut Tutorial
http://coconut.readthedocs.io/en/master/HELP.html
- Coconut FAQ
http://coconut.readthedocs.io/en/master/FAQ.html
- Coconut Documentation
http://coconut.readthedocs.io/en/master/DOCS.html
- Coconut na Redditu
https://www.reddit.com/r/Python/comments/4owzu7/coconut_functional_programming_in_python/
- Repositář na GitHubu
https://github.com/evhub/coconut
- Object-Oriented Programming — The Trillion Dollar Disaster
https://betterprogramming.pub/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7
- Goodbye, Object Oriented Programming
https://cscalfani.medium.com/goodbye-object-oriented-programming-a59cda4c0e53
- 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
- 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
- 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
- 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
- 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
- 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
- Why Programmers Need Limits
https://cscalfani.medium.com/why-programmers-need-limits-3d96e1a0a6db
- Infographic showing code complexity vs developer experience
https://twitter.com/rossipedia/status/1580639227313676288
- Python's reduce(): From Functional to Pythonic Style
https://realpython.com/python-reduce-function/
- What is the problem with reduce()?
https://stackoverflow.com/questions/181543/what-is-the-problem-with-reduce
- The fate of reduce() in Python 3000
https://www.artima.com/weblogs/viewpost.jsp?thread=98196
- Reading 16: Map, Filter, Reduce
http://web.mit.edu/6.031/www/sp22/classes/16-map-filter-reduce/
- Currying
https://sw-samuraj.cz/2011/02/currying/
- Používání funkcí v F#
https://docs.microsoft.com/cs-cz/dotnet/fsharp/tutorials/using-functions
- Funkce vyššího řádu
http://naucte-se.haskell.cz/funkce-vyssiho-radu
- Currying (Wikipedia)
https://en.wikipedia.org/wiki/Currying
- Currying (Haskell wiki)
https://wiki.haskell.org/Currying
- Haskell Curry
https://en.wikipedia.org/wiki/Haskell_Curry
- Moses Schönfinkel
https://en.wikipedia.org/wiki/Moses_Sch%C3%B6nfinkel
- ML – funkcionální jazyk s revolučním typovým systémem
https://www.root.cz/clanky/ml-funkcionalni-jazyk-s-revolucnim-typovym-systemem/
- Funkce a typový systém programovacího jazyka ML
https://www.root.cz/clanky/funkce-a-typovy-system-programovaciho-jazyka-ml/
- 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/
- Primer on Python Decorators
https://realpython.com/primer-on-python-decorators/
- Python Decorators
https://www.programiz.com/python-programming/decorator
- PythonDecorators (Python Wiki)
https://wiki.python.org/moin/PythonDecorators
- Funcy na GitHubu
https://github.com/suor/funcy/
- Welcome to funcy documentation!
https://funcy.readthedocs.io/en/stable/
- Funcy cheatsheet
https://funcy.readthedocs.io/en/stable/cheatsheet.html
- PyToolz API Documentation
https://toolz.readthedocs.io/en/latest/index.html
- Toolz (PyToolz) na GitHubu
https://github.com/pytoolz/toolz
- Fn.py: enjoy FP in Python
https://github.com/kachayev/fn.py
- Funcy na PyPi
https://pypi.org/project/funcy/
- 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/
- Funkce vyššího řádu v knihovně Underscore
https://www.root.cz/clanky/funkce-vyssiho-radu-v-knihovne-underscore/
- Awesome functional Python
https://github.com/sfermigier/awesome-functional-python
- lispy
https://pypi.org/project/lispy/
- clojure_py na indexu PyPi
https://pypi.python.org/pypi/clojure_py
- PyClojure
https://github.com/eigenhombre/PyClojure
- Hy na GitHubu
https://github.com/hylang/hy
- Hy: The survival guide
https://notes.pault.ag/hy-survival-guide/
- Hy běžící na monitoru terminálu společnosti Symbolics
http://try-hy.appspot.com/
- Welcome to Hy’s documentation!
http://docs.hylang.org/en/stable/
- Hy na PyPi
https://pypi.org/project/hy/#description
- Getting Hy on Python
https://lwn.net/Articles/596626/