12. diel - Kolekcia Set, Queue a Map v Dart
V minulej lekcii, Dátum a čas v Dart , sme si povedali niečo o dátume a času v Dart. V dnešnom tutoriále si ukážeme ďalšie kolekcie, ktoré máme dostupné as ktorých položkami môžeme pracovať inak ako chcete v nám už známom zozname.
Pojem kolekcia sme tu už spomenuli. Je to štruktúra, do ktorej môžeme
ukladať viac objektov. Kolekcií je v Dart niekoľko, sú prispôsobené pre
rôzne účely a môžeme s nimi zaobchádzať rôznymi spôsobmi. Doteraz
poznáme iba kolekciu zoznam (List
). V priebehu kurzu však budeme
potrebovať aj ďalšie kolekcie, ktoré si dnes vysvetlíme.
Set
Set
je kolekcia reprezentujúci množinu, ktorá si je veľmi
podobná s List
, avšak zásadným rozdielom je, že každý objekt
sa v nej môže vyskytovať iba raz, tj. Neuchováva duplicity. Množinu možno
ľahko previesť na zoznam a zoznam na množinu pomocou metódy
toSet()
či toList()
. Ľahko tak možno z listu
odstrániť duplicity pomocou zreťazenie týchto metód, napr.
mujList.toSet().toList()
.
Vyskúšajme si ju:
Set<int> set = new Set(); set.add(1); set.add(1); set.add(2); set.add(1); print(set);
Výstup programu:
Konzolová aplikácia
{1, 2}
Pre každý objekt zadaného typu možno určiť, či je alebo nie je v
množine. Ak začneme množinu prechádzať, budú prvky v takom poradí, v akom
boli pridané. Prvky sa rozlišujú podľa operátora ==
a je
odporúčané, ak je tento operátor prepísaný, taktiež prepísať aj metódu
hashCode()
pre zachovanie konzistencie.
Množina má taktiež oproti zoznamu niekoľko špecifických funkcií:
union()
Metóda množinového zjednotenie, ktorá vracia novú množinu s prvkami z prvej aj z druhej množiny. Druhú množinu odovzdáme parametrom. Najprv sú pridané prvky z prvej množiny v pôvodnom poradí a následne sú pridané zvyšné prvky, ktoré sú v druhej množine navyše, v poradí z druhej množiny.
Set<int> a = new Set(); a.addAll([1, 2, 1, 1, 2, 4]); Set<int> b = new Set(); b.addAll([1, 2, 2, 2, 2, 3, 3, 5]); print(a); print(b); print(a.union(b)); print(b.union(a));
Výstup programu:
Konzolová aplikácia
{1, 2, 4}
{1, 2, 3, 5}
{1, 2, 4, 3, 5}
{1, 2, 3, 5, 4}
difference()
Ďalšou zaujímavou metódou je Množinový rozdiel. Metóda vráti novú množinu s prvkami z prvej množiny, ktoré sa nevyskytovali v druhej množine. Druhú množinu opäť odovzdáme parametrom.
Set<int> a = new Set(); a.addAll([1, 2, 1, 1, 2, 4]); Set<int> b = new Set(); b.addAll([1, 2, 2, 2, 2, 3, 3, 5]); print(a); print(b); print(a.difference(b)); print(b.difference(a));
Výstup programu:
Konzolová aplikácia
{1, 2, 4}
{1, 2, 3, 5}
{4}
{3, 5}
intersection()
Posledný z množinových metód je Množinový prienikom. Metóda vráti novú množinu obsahujúce iba prvky, ktoré boli spoločné v oboch množinách.
Set<int> a = new Set(); a.addAll([1, 2, 1, 1, 2, 4]); Set<int> b = new Set(); b.addAll([1, 2, 2, 2, 2, 3, 3, 5]); print(a); print(b); print(a.intersection(b)); print(b.intersection(a));
Výstup programu:
Konzolová aplikácia
{1, 2, 4}
{1, 2, 3, 5}
{1, 2}
{1, 2}
Vlastný objekt
Ako už bolo povedané, ak chceme pracovať s množinou, objekt musí mať
implementovaný operátor ==
a metódu hashCode()
. Pre
ukážku si vytvoríme objekt Auto
, ktoré bude mať rýchlosť a
názov. Následne vytvoríme 3 autá, pričom 2 z nich budú mať rovnaké
hodnoty:
class Auto { int rychlost; String nazev; @override String toString() { return '$nazev($rychlost)'; } } void main() { Auto mazel = new Auto() ..nazev = 'Mazlík' ..rychlost = 150; Auto auto = new Auto() ..nazev = 'Mazlík' ..rychlost = 150; Auto popelnice = new Auto() ..nazev = 'Šunka' ..rychlost = 60; Set<Auto> auta = new Set(); auta.add(mazel); auta.add(auto); auta.add(popelnice); print(auta); }
Výstup programu:
Konzolová aplikácia
{Mazlík(150), Mazlík(150), Šunka(60)}
Očakávané správanie je samozrejme také, že keď používame množinu,
mali by v nej byť vo výsledku len 2 autá, pretože uchováva len unikátne
objekty. Avšak hľa - auto, ktoré identifikujeme podľa názvu a rýchlosti,
sa nám objavilo dvakrát. Zabudli sme implementovať operátor ==
a hashCode()
. Nemusíme vymýšľať relatívne zložitý kód
sami, IDE nám ho vygeneruje za nás. Stačí stlačiť klávesy ALT
+ INSERT (Generate ...) a zvoliť ==() and hashCode
.
My budeme chcieť identifikovať naše auto podľa názvu a rýchlosti, preto zvolíme obe vlastnosti.
@override bool operator ==(Object other) => identical(this, other) || other is Auto && runtimeType == other.runtimeType && rychlost == other.rychlost && nazev == other.nazev; @override int get hashCode => rychlost.hashCode ^ nazev.hashCode;
Všimnite si novinky, kľúčového slova operator
. Presne tak
možno prepísať takmer ľubovoľný operátor pre daný objekt. K
preťažovanie operátorov sa ešte vrátime a vysvetlíme si všetko viac do
hĺbky. Znovu si spustíme náš program, tentoraz už všetko funguje presne
tak, ako by sme očakávali:
Konzolová aplikácia
{Mazlík(150), Šunka(60)}
Queue
Queue
je kolekcia, ktorá opäť veľmi pripomína zoznam,
avšak reprezentuje front (FIFO) a zásobník (LIFO). To znamená, že je táto
kolekcia optimalizovaná na prístup na prvý či posledný prvok. Pre
používanie je nutné importovať knižnicu dart:collection
.
Rovnako ako zoznam alebo množina, aj front možno prechádzať a bude fungovať
aj prístup na položku na danom indexe, avšak kvôli implementácii frontu
nebude prístup tak rýchly ako v zoznamoch.
Vyskúšame si jednoduchú ukážku:
Queue<int> queue = new Queue(); queue.add(1); queue.add(2); queue.add(2); queue.add(3); print(queue);
Doteraz je správanie rovnaké so zoznamom. Ukážeme si však ďalšie metódy pre prácu s frontom.
addLast()
Metóda pre vloženie prvku na koniec fronty. Možno nahradiť metódou
add()
.
addFirst()
Metóda pre vloženie prvku na začiatok fronty.
Queue<int> queue = new Queue(); queue.add(1); queue.add(2); queue.add(2); queue.addFirst(3); print(queue);
Výstup programu:
Konzolová aplikácia
{3, 1, 2, 2}
removeFirst()
a
removeLast()
Metódy odstráni prvý / posledný prvok kolekcie a tento prvok vráti.
Queue<int> queue = new Queue(); queue.add(1); queue.add(2); queue.add(2); queue.addFirst(3); print(queue); print(queue.removeFirst()); print(queue); print(queue.removeLast()); print(queue);
Výstup programu:
Konzolová aplikácia
{3, 1, 2, 2}
3
{1, 2, 2}
2
{1, 2}
Map
Mapa, asociatívne pole, slovník, ... Všetky tieto názvy môžete poznať z rôznych programovacích jazykov. V Dart budeme používať pojem mapa. Mapa je kolekcia, ktorá uchováva svoje prvky pod zadanými kľúčmi. V takej kolekcii môžeme k prvkom pristupovať po zadaní kľúča. Rovnako ako u predchádzajúcich kolekcií, prvky môžeme prechádzať v poradí podľa pridania. Dátový typ kľúča zapisujeme do lomených zátvoriek na prvé miesto a na druhej píšeme dátový typ prvku. Ukážme si ukážku:
Map<int, String> mapa = new Map(); mapa[0] = 'nula'; mapa[1] = 'uno'; mapa[2] = 'два'; print(mapa);
Výstup programu:
Konzolová aplikácia
{0: nula, 1: uno, 2: два}
Ako ste si iste všimli už z ukážky, mapa nemá metódu
add()
. Ak chceme pridať prvok do mapy, zapíšeme kľúč do
hranatých zátvoriek a pomocou operátora rovná sa vložíme prvok. Mapa,
podobne ako zoznam, možno zapísať pomocou doslovný, pre ktorý sa
používajú zložené zátvorky, v ktorých zapisujeme dvojice
klíč: prvek
oddelené čiarkou. V ukážke si Namapujte postavy
zo seriálu Simpsonovci na ich obľúbenú vec, aby sme si ukázali, že mapa
nemusí mať na rozdiel od zoznamu číselné kľúče, ale že môžeme
indexovať aj reťazci:
Map<int, String> mapa = { 'Homer': 'kobliha', 'Marge': 'trouba', 'Bart': 'prak', 'Liza': 'kniha', 'Meggie': 'dudlík', };
keys
a values
Kľúče a prvky mapy sa dajú získať z kolekcií keys
a
values
.
putIfAbsent()
Metóda vhodná pre pridanie prvku iba v prípade, že už taký kľúč neexistuje:
Map<int, String> mapa = { 0: 'nula', 1: 'uno', 2: 'два', }; mapa.putIfAbsent(2, () => 'dva'); // nepřepíše print(mapa); mapa[2] = 'zwei'; // přepíše print(mapa);
Výstup programu:
Konzolová aplikácia
{0: nula, 1: uno, 2: два}
{0: nula, 1: uno, 2: zwei}
containsKey()
a
containsValue()
Metódy slúžiace pre určenie, či sa daný kľúč alebo prvok nachádza v kolekcii:
Map<int, String> mapa = { 0: 'nula', 1: 'uno', 2: 'два', }; print(mapa.containsKey(2)); print(mapa.containsKey(3)); print(mapa.containsValue('uno')); print(mapa.containsValue('jedna'));
Výstup programu:
Konzolová aplikácia
true
false
true
false
V budúcej lekcii, Diár s databázou v Dart , si naprogramujeme pomocou kolekcií databázu, bude to elektronický diár!:)
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é 4x (2.29 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Dart