Zoznamy, n-tice, množiny a slovníky sa dajú do seba vnárať: zoznam zoznamov vytvorí tabuľku, zoznam slovníkov databázu triedy, slovník zoznamov rozvrh. V tejto téme sa naučíš pracovať s dvojrozmernými zoznamami (mriežkami, maticami), s vnorenými štruktúrami a s dvoma dôležitými spôsobmi ukladania údajov – zásobníkom a radom.
Čo sa naučíš
- vytvoriť dvojrozmerný zoznam, pristupovať k prvkom
m[riadok][stĺpec]a prechádzať ho, - vyhnúť sa chybe so zdieľanými riadkami,
- pracovať so zoznamom slovníkov a slovníkom zoznamov,
- použiť zásobník (LIFO) a rad (FIFO) a vedieť, kde sa hodia.
1Dvojrozmerný zoznam
Tabuľku (maticu, mriežku) uložíme ako zoznam riadkov, kde každý riadok je zoznam:
Výstup:
[1, 2, 3]
6
riadkov: 2 stĺpcov: 3
[[1, 20, 3], [4, 5, 6]]| stĺpec 0 | stĺpec 1 | stĺpec 2 | |
|---|---|---|---|
| riadok 0 | m[0][0] = 1 | m[0][1] = 2 | m[0][2] = 3 |
| riadok 1 | m[1][0] = 4 | m[1][1] = 5 | m[1][2] = 6 |
Prvý index vyberá riadok, druhý stĺpec v ňom: m[riadok][stĺpec].
1.1Vytvorenie mriežky
Mriežku r × s vyplnenú nulami vytvoríme generátorovým zápisom – každý riadok musí byť samostatný zoznam:
Výstup:
[0, 0, 0, 0]
[0, 0, 7, 0]
[0, 0, 0, 0]Výstup:
[0, 0, 7, 0]
[0, 0, 7, 0]
[0, 0, 7, 0](Je to rovnaký jav ako b = a pri zoznamoch – viac mien pre jeden zoznam.)
1.2Prechádzanie a výpis
Dva vnorené cykly: vonkajší cez riadky, vnútorný cez stĺpce (prvky riadku):
Výstup:
3 8 1
9 4 7
2 6 5Ak potrebujeme indexy (napríklad pri susedoch či diagonále), prechádzame range:
Výstup:
hlavná diagonála: [3, 4, 5] súčet: 12
m[0][1] = 8
m[1][0] = 9
m[1][2] = 7
m[2][1] = 61.3Súčty riadkov a stĺpcov
Súčet riadku je jednoduchý (sum(riadok)). Pre stĺpec musíme prejsť všetky riadky a z každého vziať prvok s rovnakým indexom:
Výstup:
predajňa 0: 365
predajňa 1: 320
predajňa 2: 450
mesiac 0: 360
mesiac 1: 375
mesiac 2: 4002Vnorené štruktúry
2.1Zoznam slovníkov
Každý záznam (osoba, výrobok, kniha) je slovník s rovnakými kľúčmi; všetky záznamy tvoria zoznam. Je to v Pythone najbežnejší spôsob, ako uchovávať „tabuľkové“ údaje:
Výstup:
Ema 47
Ján 38
Sofia 50
Najviac bodov: Sofia
3.A: ['Ema', 'Sofia']2.2Slovník zoznamov
Ak k jednému kľúču patrí viac hodnôt, hodnotou je zoznam:
Výstup:
pondelok: matematika, informatika, fyzika (3 h)
utorok: slovenčina, informatika, telesná (3 h)
Informatika v pondelok: TruePrístup k vnoreným údajom sa číta zľava doprava: rozvrh["utorok"] je zoznam, rozvrh["utorok"][0] jeho prvý prvok.
3Zásobník
Zásobník (stack) je štruktúra, do ktorej pridávame aj z nej odoberáme na tom istom konci – ako kopa tanierov. Prvok, ktorý prišiel posledný, odchádza prvý: LIFO (last in, first out).
V Pythone je zásobníkom obyčajný zoznam: append pridá na vrch, pop() vráti a odoberie prvok z vrchu.
Výstup:
vložené A → ['A']
vložené B → ['A', 'B']
vložené C → ['A', 'B', 'C']
vybraté C → ['A', 'B']
vybraté B → ['A']
vybraté A → []Zásobník sa používa napríklad pri funkcii Späť (undo) v editoroch, pri návrate na predchádzajúcu stránku v prehliadači a pri volaniach funkcií (zásobník volaní – téma Rekurzia).
3.1Kontrola zátvoriek
Klasická úloha so zásobníkom: sú zátvorky vo výraze správne spárované? Každú otváraciu zátvorku vložíme na zásobník. Pri zatváracej musí byť na vrchu zodpovedajúca otváracia – vyberieme ju. Na konci musí byť zásobník prázdny.
Výstup:
(a + b) * [c - d] True
((a + b) False
(a + b)) False
[(a + b]) False
{[()]} True4Rad
Rad (fronta, queue) funguje ako rad pri pokladni: pridáva sa na koniec, odoberá sa zo začiatku. Čo prišlo prvé, odchádza prvé: FIFO (first in, first out).
So zoznamom by sme odoberali pop(0) – to je však pri dlhom zozname pomalé, lebo všetky ostatné prvky sa musia posunúť. Python má na rad štruktúru deque z modulu collections s rýchlymi operáciami na oboch koncoch:
Výstup:
v rade: ['Ema', 'Ján', 'Sofia']
obslúžený: Ema → v rade: ['Ján', 'Sofia']4.1Simulácia radu pri pokladni
Zadanie: Ľudia prichádzajú k pokladni v zadaných minútach a obsluha jednej osoby trvá 3 minúty. Pre každú osobu vypíš, kedy bola obslúžená a koľko minút čakala.
Riešenie: Osoby vkladáme do radu v poradí príchodu. Pokladňa obsluhuje vždy osobu, ktorá je v rade prvá; obsluha začne, keď je pokladňa voľná a osoba už prišla.
Výstup:
Ema príchod 0, obsluha 0– 3, čakanie 0 min
Ján príchod 1, obsluha 3– 6, čakanie 2 min
Sofia príchod 2, obsluha 6– 9, čakanie 4 min
Tomáš príchod 9, obsluha 9–12, čakanie 0 minZásobník a rad sú základom mnohých algoritmov – napríklad prehľadávania bludiska alebo grafu.
5Riešené úlohy
5.1Piškvorky: kto vyhral?
Zadanie: Hracia plocha 3 × 3 je dvojrozmerný zoznam so znakmi "X", "O" a ".". Napíš funkciu, ktorá zistí, či má niektorý znak tri v rade – v riadku, stĺpci alebo na diagonále.
Výstup:
Tri v rade má: XFunkcia najprv zostaví všetkých 8 „čiar“ (3 riadky, 3 stĺpce, 2 diagonály) a potom každú skontroluje rovnakým spôsobom – vyhneme sa tak opakovaniu kódu.
5.2Počet mín v susedstve
Zadanie: V mriežke sú míny (*) a prázdne políčka (.). Pre každé prázdne políčko vypíš počet mín na 8 susedných políčkach (ako v hre Míny).
Riešenie: Susedia políčka [r][s] majú indexy r + dr, s + ds, kde dr a ds sú −1, 0 alebo 1 (okrem dvojice 0, 0). Pri okrajoch treba overiť, že index neleží mimo mriežky – inak by záporný index „pretiekol“ na druhú stranu a priveľký by spôsobil chybu.
Výstup:
*211
12*1
0111Mriežku sme tu uložili ako zoznam reťazcov – reťazce sa tiež dajú indexovať pole[r][s], iba sa nedajú meniť.
5.3Transponovaná matica
Zadanie: Vymeň v matici riadky a stĺpce (prvý riadok sa stane prvým stĺpcom).
Výstup:
[[1, 4], [2, 5], [3, 6]]6Časté chyby
[[0] * s] * rvytvorí zdieľané riadky – použi[[0] * s for _ in range(r)].- Zámena indexov:
m[riadok][stĺpec], nie naopak; pri súradniciachx,yje tom[y][x]. - Okraje mriežky: pri susedoch kontroluj
0 <= r < pocet_riadkov; záporný index nespôsobí chybu, ale vráti prvok z druhého konca! pop(0)na dlhom zozname je pomalé – na rad použideque.popleft().- Kopírovanie vnorených zoznamov:
m.copy()skopíruje iba vonkajší zoznam, riadky ostanú zdieľané. Kópia riadkov:[riadok.copy() for riadok in m].
Zhrnutie
- Dvojrozmerný zoznam = zoznam riadkov;
m[r][s],len(m)riadkov,len(m[0])stĺpcov. - Mriežku vytváraj
[[hodnota] * s for _ in range(r)]. - Prechádzanie: vnorené cykly; stĺpec:
[m[r][s] for r in range(len(m))]. - Zoznam slovníkov pre záznamy, slovník zoznamov pre viac hodnôt k jednému kľúču.
- Zásobník (LIFO):
append+pop(); rad (FIFO):deque+append+popleft().
Úlohy na precvičenie
- Vytvor tabuľku násobenia 10 × 10 ako dvojrozmerný zoznam a vypíš ju zarovnanú.
- Nájdi v matici najväčší prvok a vypíš jeho riadok a stĺpec.
- Zisti, či je štvorcová matica symetrická (
m[r][s] == m[s][r]pre všetky r, s). - Zo zoznamu slovníkov (meno, trieda, body) vypočítaj priemer bodov pre každú triedu.
- Pomocou zásobníka obráť poradie slov vo vete.
- Simuluj hru „horúci zemiak“: deti v kruhu si podávajú zemiak, každé k-té vypadne; vypíš poradie vypadávania (pomôže
deque.rotate).