8. diel - Zoznamy v Dart
V minulej lekcii kurzu, Ošetrenie užívateľských vstupov v Dart , sme si ukázali ošetrenie užívateľských vstupov. Dnes si v tutoriálu programovacieho jazyka Dart predstavíme dátovú štruktúru zoznam a vyskúšame si, čo všetko vie.
Zoznam
Predstavte si, že si chcete uložiť nejaké údaje o viac prvkoch. Napr.
chcete v pamäti uchovávať 10 čísel, políčka šachovnice alebo mena 50tich
užívateľov. Asi vám dôjde, že v programovaní bude nejaká lepšia cesta,
než začať búšiť premenné uzivatel1
,
uzivatel2
... až uzivatel50
. Nehľadiac na to, že ich
môže byť potrebné 1000. A ako by sa v tom potom hľadalo? Brrr, takto
nie.:)
Ak potrebujeme uchovávať väčšie množstvo premenných rovnakého
typu, tento problém nám rieši zoznam. Môžeme si ho predstaviť ako
rad priehradiek, kde v každej máme uložený jeden prvok. Priehradky sú
očíslované tzv. Indexy, prvý má index 0
.
Programovacie jazyky sa veľmi líšia v tom, ako s podobnými dátovými štruktúrami pracujú. V niektorých jazykoch (najmä starších, kompilovaných) nebolo možné za behu programu vytvoriť zoznam s dynamickou veľkosťou (napr. Mu dať veľkosť podľa nejaké premenné). Takým zoznamom sa hovorí poľa. Pole sa muselo deklarovať s konštantnou veľkosťou priamo v zdrojovom kóde. Toto sa obchádzalo tzv. Pointer a vlastnými dátovými štruktúrami, čo často viedlo k chybám pri manuálnej správe pamäte a nestabilite programu (napr. V C ++). Naopak niektoré interpretované jazyky umožňujú nielen deklarovať zoznam s ľubovoľnou veľkosťou, ale dokonca túto veľkosť na už existujúcom zozname meniť (napr. PHP). Ako som už hovoril, v Dart je všetko objekt. V rámci tohto kurzu nám bude stačiť vedieť, čo to zoznam všeobecne je a že kolekcie sú chytré dátové štruktúry, ktoré nám uľahčujú prácu. O kolekciách ako takých si niečo povieme až v kurze o objektovom programovaní v Dart.
Zoznam je jednoduchý, prvky sú za sebou a môžeme ich ľahko prechádzať. Pre hromadnú manipuláciu s prvkami zoznamu sa používajú cykly. To isté platí aj pre zoznamy v Dart, preto sú ideálnym kandidátom, ktorého budeme používať.
Zoznam deklarujeme ako List (čo je zoznam anglicky) a do špicatých zátvoriek pridáme typ položiek zoznamu.
List<int> seznam;
Zoznam je samozrejme názov našej premennej. Teraz sme však len
deklarovali, že v premennej bude zoznam intů. Teraz ho musíme založiť, aby
sme ho mohli používať. K tomu buď využijeme literal (možnosť, ako
explicitne niečo zapísať, napr. 3 pre celočíselný literál). Literál pre
zoznam je [ ]
, alebo použijeme kľúčové slovo new
,
ktoré sa využíva pri zložitejších objektov, čo si vysvetlíme
podrobnejšie v už spomínanom nadväzujúcom kurzu.
List<int> seznam = []; List<int> seznam2 = new List();
Teraz máme v premennej seznam
a seznam2
zoznamy,
ktoré sa samy zväčšujú či zmenšujú podľa potrieb.
Do zoznamu pridávame prvky metódou add()
, ktorá ako parameter
berie daný prvok. K prvkom zoznamov pristupujeme cez hranatú zátvorku, do
ktorej píšeme index daného prvku (ten musí existovať).
seznam.add(1); print(seznam[0]);
Plniť zoznam takhle ručne by bolo príliš pracné, použijeme cyklus a
naplníme si zoznam číslami od 1 do 10. K naplneniu použijeme
for
cyklus:
for (int i = 0; i < 10; i++) seznam.add(i + 1);
Aby sme zoznam vypísali, môžeme za predchádzajúci kód pripísať:
for (int i = 0; i < seznam.length; i++) print(seznam[i]);
Výstup programu:
Konzolová aplikácia
1
2
3
4
5
6
7
8
9
10
Všimnite si, že zoznam má vlastnosť length
, kde je uložená
jeho dĺžka, teda počet prvkov.
A alebo, pretože ako som spomínal, zoznam v Dart je kolekcia a tá sa vie
sama vypísať, môžeme vypísať celý zoznam naraz pomocou metódy
print()
:
print(seznam);
Výstup programu:
Konzolová aplikácia
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Môžeme použiť zjednodušenú verziu cyklu pre prácu s kolekciami, známu ako foreach. Ten prejde všetky prvky v zozname a jeho dĺžku si zistí sám. Jeho syntax pre náš zoznam je nasledovné:
for (datovytyp promenna in kolekce) { // příkazy }
Kolekcia v Dart majú navyše metódy na zjednodušený zápis foreach cyklu a ďalších špeciálnych cyklov.
kolekce.forEach((datovytyp promenna) {
// příkazy
});
Cyklus prejde prvky v kolekcii (to je všeobecný názov pre štruktúry, ktoré obsahujú viac prvkov, u nás to bude zoznam) postupne od prvého do posledného. Prvok máme v každej iterácii cyklu uložený v danej premennej.
Prepíšme teda náš doterajší program na metódu forEach()
.
Foreach nemá riadiace premennú, nie je teda vhodný pre vytvorenie nášho
zoznamu a použijeme ho len pre výpis.
seznam.forEach((int promenna) { stdout.write('$promenna '); });
Výstup programu:
Konzolová aplikácia
1 2 3 4 5 6 7 8 9 10
Zoznam samozrejme môžeme naplniť ručne a to aj bez toho, aby sme prvky postupne dosadzovali. Použijeme k tomu literal zoznamu, ktorý som spomínal už skôr, a prvky v ňom oddelíme čiarkou:
List<String> simpsonovi = ['Homer', 'Marge', 'Bart', 'Lisa', 'Meggie'];
Zoznam často slúži na ukladanie medzivýsledkov, ktoré sa potom ďalej v programe používajú. Keď potrebujeme nejaký výsledok 10x, tak to nebudeme 10x počítať, ale spočítame to raz a uložíme do zoznamu, odtiaľ potom výsledok len načítame.
Metódy a vlastnosti na triede List
Samotný List obsahuje množstvo užitočných metód a vlastností pre prácu so zoznamami. Poďme sa na ne pozrieť:
Sort ()
Ako už názov napovedá, metóda nám zoznam zoradí. Jej jediný parameter
je komparátor, špeciálna metóda, ktorá určí, ako položky v zozname
zoradiť. String
má v Dart metódu, ktorá porovná seba voči
inému STRING. Túto metódu využijeme. Skúsme si zotrieďiť a vypísať
našu rodinku Simpson:
List<String> simpsonovi = ['Homer', 'Marge', 'Bart', 'Lisa', 'Meggie']; print(simpsonovi); simpsonovi.sort((String a, String b) => a.compareTo(b)); print(simpsonovi);
Výstup programu:
Konzolová aplikácia
[Homer, Marge, Bart, Lisa, Meggie]
[Bart, Homer, Lisa, Marge, Meggie]
Skúste si vytvoriť zoznam čísel a vyskúšajte si, že to naozaj funguje
aj pre nich. Rovnako tak aj int
má metódu
compareTo()
.
Reversed
Vlastnosť reversed
nám vráti otočený zoznam (prvý prvok
bude ako posledná atď.), Toho môžeme využiť napr. Pre triedenie pospiatky.
Táto vlastnosť nevracia zoznam, ale všeobecnú kolekciu, ktorú možno
prechádzať. Ak by sme chceli vrátiť zoznam, na vlastnosť
reversed
zavoláme ešte metódu toList()
.
List<String> simpsonovi = ['Homer', 'Marge', 'Bart', 'Lisa', 'Meggie']; simpsonovi.sort((String a, String b) => a.compareTo(b)); print(simpsonovi.reversed); print(simpsonovi.reversed.toList());
Výstup programu:
Konzolová aplikácia
(Meggie, Marge, Lisa, Homer, Bart)
[Meggie, Marge, Lisa, Homer, Bart]
IndexOf () a lastIndexOf ()
Tieto metódy vráti index prvého alebo posledného nájdeného prvku. V
prípade nenájdenia prvku vráti -1. Každá z metód berie dva parametre,
prvým je hľadaný prvok, druhý nepovinný parameter je index, od ktorého
začať. Umožníme užívateľovi zadať meno Simpsons a povieme mu, na akej
pozícii je uložený. Teraz to pre nás nemá hlbší význam, pretože prvok
zoznamu je len String
. Bude sa nám to však veľmi hodiť vo
chvíli, kedy v poli budeme mať uložené plnohodnotné objekty. Berme to teda
ako takú prípravu.
List<String> simpsonovi = ['Homer', 'Marge', 'Bart', 'Lisa', 'Meggie']; print('Ahoj, zadej svého oblíbeného Simpsna (z rodiny Simpsnů): '); String simpson = stdin.readLineSync(encoding: UTF8); int pozice = simpsonovi.indexOf(simpson); if (pozice >= 0) print('Jo, to je můj ${pozice + 1}. nejoblíbenější Simpson!'); else print('Hele, tohle není Simpson!');
Výstup programu:
Konzolová aplikácia
Ahoj, zadej svého oblíbeného Simpsna (z rodiny Simpsnů):
Homer
Jo, to je můj 1. nejoblíbenější Simpson!
Sublist ()
Sublist vracia výrez zoznamu od štartového indexu do konca alebo do koncového indexu, pričom tento index sa vo výreze už neobjaví.
List<String> simpsonovi = ['Homer', 'Marge', 'Bart', 'Lisa', 'Meggie']; print(simpsonovi.sublist(2, 4));
Výstup programu:
Konzolová aplikácia
[Bart, Lisa]
Length
Vlastnosť length
sme si už spomenuli, vráti dĺžku zoznamu.
Nie je metódou, ale vlastností, nepíšu sa za ňu teda zátvorky ().
First a last
Vlastnosti vracajúci prvý a posledný prvok zoznamu.
Take () a skip ()
Obe tieto metódy berú ako parameter počet prvkov. Take vráti zoznam s daným počtom prvkov skopírovaných od začiatku pôvodného zoznamu. Skip () naopak vráti zoznam bez týchto prvých prvkov.
Contains ()
Metóda vracia true
/ false
podľa toho, či sa
prvok, uvedený v parametri metódy, v danom poli nachádzajú.
List<String> simpsonovi = ['Homer', 'Marge', 'Bart', 'Lisa', 'Meggie']; print(simpsonovi.contains('Bart')); print(simpsonovi.contains('Superman'));
Výstup programu:
Konzolová aplikácia
true
false
Shuffle ()
Shuffle () je metóda, ktorá náhodne prohází prvky zoznamu. Nič nevracia, operuje nad konkrétnym zoznamom, ktorému v zásade len prohází indexy.
List<String> simpsonovi = ['Homer', 'Marge', 'Bart', 'Lisa', 'Meggie']; print(simpsonovi); simpsonovi.shuffle(); print(simpsonovi); simpsonovi.shuffle(); print(simpsonovi);
Výstup programu:
Konzolová aplikácia
[Homer, Marge, Bart, Lisa, Meggie]
[Bart, Marge, Lisa, Homer, Meggie]
[Homer, Bart, Marge, Meggie, Lisa]
To by pre dnešok stačilo, môžete si so zoznamom hrať. V budúcej lekcii, Riešené úlohy k 7.-8. lekciu Dart , na vás čaká prekvapenie.;-)
V nasledujúcom cvičení, Riešené úlohy k 7.-8. lekciu Dart, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 6x (2.15 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Dart