Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 11 - Vnořené seznamy v Dartu

V předešlém cvičení, Řešené úlohy k 10. lekci Dartu, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

V minulé lekci, Řešené úlohy k 10. lekci Dartu, jsme si uvedli metody split() a join() na textových řetězcích. Dnešní Dart tutoriál pojednává o tzv. vícerozměrných polích, pro nás konkrétně o vnořených seznamech.

Již umíme pracovat s jednorozměrným polem (seznamem), které si můžeme představit jako řádku přihrádek v paměti počítače.

Seznam v jazyce Dart - Základní konstrukce jazyka Dart

(Na obrázku je vidět pole osmi čísel)

Ačkoli to není tak časté, v programování se občas setkáváme i s vícerozměrnými poli a to zejména pokud programujeme nějakou simulaci (např. hru).

Dvourozměrné pole

Dvourozměrné pole si můžeme v paměti představit jako tabulku a mohli bychom takto reprezentovat např. rozehranou partii piškvorek. Pokud bychom se chtěli držet reálných aplikací, které budete později v zaměstnání tvořit, můžeme si představit, že do 2D pole budeme ukládat informace o obsazenostech sedadel v kinosálu. Situaci bychom si mohli graficky znázornit např. takto:

2D pole v Dartu - Základní konstrukce jazyka Dart

(Na obrázku je vidět 2d pole reprezentující obsazenost kinosálu)

Kinosál by byl v praxi samozřejmě větší, ale jako ukázka nám toto pole postačí. Hodnota 0 označuje volno, 1 obsazeno. Později bychom mohli doplnit i 2 – rezervováno a podobně. Pro tyto stavy by bylo správnější vytvořit si vlastní datový typ, tzv. výčet, ale s ním se setkáme až později, takže si teď musíme vystačit pouze s čísly.

Připomenu, že pole je pro nás v Dartu seznam. Vnořený seznam v Dartu deklarujeme následujícím způsobem:

List<List<int>> kinosal = [];

V tomto případě chceme kinosál na začátku definovat do určitého tvaru. Toho docílíme tak, že bychom ve for cyklu přidali do seznamu seznamy, do kterých bychom přidali dané hodnoty. Nebo použijeme sofistikovanější zápis, který se pro jeho momentální náročnost v rámci tohoto tutoriálu nebudeme snažit vysvětlit.

List<List<int>> kinosal = new List.generate(5, (_) => new List.filled(5, 0));

Popíši kód alespoň jednoduše, i když zatím nevíme, proč to takto funguje: vytvoříme si seznam, který v sobě vygeneruje 5x seznam, který v sobě má 5x číslo 0.

První číslice udává počet sloupců, druhá počet řádků (samozřejmě si to můžeme určit i obráceně, např. matice v matematice se zapisují opačně).

Naplnění daty

Nyní kinosál naplníme jedničkami tak, jak je vidět na obrázku výše. Protože budeme jako správní programátoři líní, využijeme k vytvoření řádku jedniček for cykly. :) Pro přístup k prvku seznamu musíme samozřejmě zadat 2 souřadnice. Vypíšeme si také obsah kinosálu před a po:

print(kinosal);
kinosal[2][2] = 1; // Prostředek
for (int i = 1; i < 4; i++) // 4. řádek
{
    kinosal[i][3] = 1;
}
for (int i = 0; i < 5; i++) // Poslední řádek
{
    kinosal[i][4] = 1;
}
print(kinosal);

Výstup programu:

Konzolová aplikace
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
[[0, 0, 0, 0, 1], [0, 0, 0, 1, 1], [0, 0, 1, 1, 1], [0, 0, 0, 1, 1], [0, 0, 0, 0, 1]]

Jak jde vidět, jedničky se nám někde zapsaly a pokud porovnáme výstup s obrázkem výše, opravdu se vše i shoduje.

Výpis

Výpis pole opět provedeme pomocí cyklu, na vnořený budeme potřebovat cykly 2 (jeden nám proiteruje sloupce a druhý řádky). Jako správní programátoři nevložíme počet řádků a sloupců do cyklů napevno, jelikož se může změnit. Využijeme vlastnosti length na seznamu. Pozor ale, že vrátí počet prvků v konkrétním seznamu, ne celkový počet. Výraz kinosal.length nám vrátí počet sloupců, kinosal.first.length vrátí počet sedadel v prvním sloupci. Jelikož v našem kině mají všechny sloupce stejný počet sedadel, můžeme druhou hodnotu brát jako počet řad sálu.

for (int j = 0; j < kinosal.length; j++)
{
    for (int i = 0; i < kinosal.first.length; i++)
    {
        stdout.write(kinosal[i][j]);
    }
    stdout.writeln();
}

Výstup programu:

Konzolová aplikace
00000
00000
00100
01110
11111

I náš výpis vnořeného seznamu dopadl dobře. Obdobně bychom takto mohli tvořit i více zanořené seznamy, stačilo by do položek vnořeného seznamu vygenerovat další seznamy. Celek si poté můžeme představit jako by kinosál měl ještě další patra.

3D pole v programovacím jazyce Dart - Základní konstrukce jazyka Dart

Seznam seznamů

Někdy nepožadujeme všechny seznamy v seznamu stejně velké, výsledkem bude "zubatý" seznam seznamů jako na obrázku níže.

Zubatá pole v programovacím jazyce Dart - Základní konstrukce jazyka Dart

Výhodou je, že do každého řádku/sloupce můžeme uložit jak veliký seznam chceme. V některých případech tedy nemusíme "plýtvat" pamětí na celou tabulku a můžeme seznam vytvořit takto "zubatě" (anglicky jagged).

Takovýto seznam vytvoříme jednoduše pomocí deklarace, kterou jsme již jednou zkoušeli:

List<List<int>> kinosal = [];

Nevýhodou tohoto přístupu je, že si všechny hodnoty musíme vložit sami a musíme také kontrolovat, že prvek, který chceme získat, opravdu existuje.

Ruční inicializace vnořených seznamů

Ještě si ukážeme, že i pro vnořené seznamy je možné použít definici formou literálu:

List<List<int>> kinosal = [
    [0, 0, 0, 0, 1],
    [0, 0, 0, 1, 1],
    [0, 0, 1, 1, 1],
    [0, 0, 0, 1, 1],
    [0, 0, 0, 0, 1],
];

(Pole je v tomto zápisu otočené, jelikož definujeme sloupce, které zde zapisujeme jako řádky).

Na závěr bych rád dodal, že někteří lidé, kteří neumí správně používat objekty, využívají vnořené seznamy k ukládání více údajů o jediné entitě. Např. budeme chtít uložit výšku, šířku a délku pěti mobilních telefonů. Ačkoli se vám nyní může zdát, že se jedná o úlohu na 3D pole, ve skutečnosti se jedná o úlohu na obyčejné 1D pole (přesněji seznam) objektů typu Telefon. Ale o tom až u objektově orientovaného programování.

V příští lekci, Matematické funkce v Dartu a knihovna dart:math, se podíváme na matematické funkce.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 10x (1.78 kB)
Aplikace je včetně zdrojových kódů v jazyce Dart

 

Předchozí článek
Řešené úlohy k 10. lekci Dartu
Všechny články v sekci
Základní konstrukce jazyka Dart
Přeskočit článek
(nedoporučujeme)
Matematické funkce v Dartu a knihovna dart:math
Článek pro vás napsal Honza Bittner
Avatar
Uživatelské hodnocení:
2 hlasů
FIT ČVUT alumnus :-) Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Aktivity