13. diel - List
V minulej lekcii, Dátum a čas v C# - DateOnly a TimeOnly, sme si precvičili použitie štruktúr
DateOnly
a TimeOnly
.
Dnes si v C# tutoriále ukážeme jednu kolekciu, ktorá je múdrejší, než pole. Umožňuje totiž prvky ľubovoľne pridávať a mazať.
Pojem kolekcie sme tu už spomínali. Je to štruktúra, do ktorej môžeme
ukladať viacero objektov. Kolekcií je v .NET frameworku veľké množstvo, sú
prispôsobené na rôzne účely a môžeme s nimi zaobchádzať rôznymi
spôsobmi. Preto im je venovaný aj celý kurz Kolekcie a LINQ. Doteraz poznáme iba kolekciu
poľa. V priebehu kurzu však budeme potrebovať niečo múdrejšie, kam budeme
môcť jednoducho za behu programu pridávať a mazať
záznamy. Iste by sa nám hodilo si v pamäti spravovať databázu
nejakých objektov. Vieme, že pole má konštantnú veľkosť, čo je daň za
jeho vysokú rýchlosť. Teraz si predstavíme List
, ktorý
môžeme chápať ako nadstavbu poľa.
List
List
je tzv. generická kolekcia. Pojem genericita
si plne vysvetlíme až pri kolekciách, teraz nám bude stačiť vedieť, že
pri deklarácii List
u musíme špecifikovať dátový typ
objektov, ktoré v ňom budú uložené. Začnime jednoducho a urobme si
List
čísel, ktoré budeme náhodne žrebovať.
Žrebovanie
Program sa nás vždy spýta, či chceme žrebovať ďalšie číslo a to sa
pridá do List
. Pokiaľ už nebudeme chcieť žrebovať, program
vypíše žrebované čísla, zoradené od najmenšieho po najväčšie.
Založme si nový projekt ListLottery
a vytvorme si triedu
Lottery
. Trieda bude obsahovať List
typu
int
, kde budú čísla uložené. List
bude privátny
a bude slúžiť iba ako interné úložisko danej triedy, aby sa naň zvonku
nedalo pristupovať. List
deklarujeme takto:
List<int> numbers;
Dátový typ píšeme pri generických kolekciách do špicatých
zátvoriek. List
je samozrejme objekt, ako každý iný.
Rovnako ako pri poli a iných objektoch, aj tu premennú pred použitím
inicializujeme:
List<int> numbers = new List<int>();
Všimnite si zátvorku, ktorú značí konštruktor. Takýto list teda
umiestnime do našej triedy, spolu s náhodným generátorom
Random
. V konštruktore atribúty inicializujeme:
class Lottery { private List<int> numbers; private Random random; public Lottery() { random = new Random(); numbers = new List<int>(); } }
Ďalej pridáme metódy Lot()
a Print()
, kde
Lot()
pridá do List
nové náhodné číslo a tiež
ho vráti ako návratovú hodnotu. Print()
vráti textový reťazec
na vypísanie. Ten bude obsahovať čísla z numbers
, zoradené a
oddelené medzerou.
Žrebovanie náhodného čísla už poznáme z lekcie
o hracej kocke, tu budeme vyhadzovať čísla od 1
do
100
. Číslo do List
u pridáme pomocou metódy
Add()
:
public int Lot() { int number = random.Next(100) + 1; numbers.Add(number); return number; }
Veľmi jednoduché, že? Kolekcia List
je interne pomerne
zložitá a zatiaľ sa nebudeme zaoberať tým, čo sa vo vnútri deje. To je
napokon účel .NET frameworku, ponúkať kvalitné a sofistikované komponenty,
ktoré sa jednoducho používajú.
Výpis čísel bude ešte jednoduchší. Na zotriedenie použijeme metódu
Sort()
na List
u, ktorá list
zotriedi. Je podobná metóde Sort()
na triede Array
.
Metóda nič nevracia, iba List
vo vnútri zotriedi:
public string Print() { string s = ""; numbers.Sort(); foreach (int i in numbers) s += i + " "; return s; }
Hotovo.
Presuňme sa do Main()
a pomocou while
cyklu
umožnime užívateľovi ovládať objekt. Podobný program bola kalkulačka z
prvých lekcií, kde sme sa v cykle pýtali, či si používateľ praje
opakovať výpočet. Tu budeme postupovať totožne.
Ovládanie bude pomocou možností 1, 2, 3 (losuj, vypíš, koniec). Budeme
ich načítať pomocou Console.ReadKey()
ako char
, nie
ako string
. Nezabudnite teda, že znaky zapisujeme pomocou
apostrofov, nie úvodzoviek:
Lottery lottery = new Lottery(); Console.WriteLine("Welcome to our lottery program."); char choice = '0'; // main loop while (choice != '3') { // option list Console.WriteLine("1 - Lot the next number"); Console.WriteLine("2 - Print numbers"); Console.WriteLine("3 - Quit"); choice = Console.ReadKey().KeyChar; Console.WriteLine(); // reaction to choice switch (choice) { case '1': Console.WriteLine("You got a: {0}", lottery.Lot()); break; case '2': Console.WriteLine("Numbers drawn: {0}", lottery.Print()); break; case '3': Console.WriteLine("Thanks for using our Lotto program"); break; default: Console.WriteLine("Invalid option. Please, try again."); break; } }
Priebeh programu je z kódu dobre viditeľný. Najprv nastavíme voľbu na
nejakú východiskovú hodnotu, aby cyklus prvýkrát prebehol. Potom voľbu
načítame z klávesnice ako znak. Znak spracujeme pomocou konštrukcie
switch
a vykonáme príslušné akcie. Pokiaľ bolo zadané niečo
iné, pokryje to možnosť default
:
Konzolová aplikácia
...
1 - Lot the next number
2 - Print numbers
3 - Quit
1
You got a: 52
1 - Lot the next number
2 - Print numbers
3 - Quit
1
1 - Lot the next number
2 - Print numbers
3 - Quit
1
1 - Lot the next number
2 - Print numbers
3 - Quit
2
Numbers drawn: 10 12 13 14 21 22 23 24 28 28 42 45 52 52 57 58 59 70 71 72 79 83 86 89
1 - Lot the next number
2 - Print numbers
3 - Quit
Vidíme, že môžeme stále pridávať nové a nové čísla. Máme oveľa
väčšie možnosti, než s poľom. Zároveň však môžeme s List
pracovať úplne rovnako, ako sme pracovali s poľom.
Môžeme používať indexáciu pomocou hranatých zátvoriek, ale pozor, prvok musí existovať. Skúsme si napísať nasledujúci kód:
List<string> l = new List<string>(); l.Add("First"); Console.WriteLine(l[0]); l[0] = "First item"; Console.WriteLine(l[0]); l[1] = "Second item"; // causes an error
Vytvoríme si List
string
. Pridáme položku
"First" a potom vypíšeme položku na indexe 0
. Vypíše sa nám
"First". Môžeme na ňu samozrejme aj takto zapisovať. S druhou položkou na
pozícii 1
však už nemôžeme pracovať, pretože sme ju do listu
nepridali. Pri poli sme zadali veľkosť a on všetky "priehradky" (premenné
pod indexy) založil. Teraz veľkosť nezadávame a "priehradky" si pridávame
sami.
Pozrime sa na List
podrobnejšie a vypíšme si metódy, ktoré
sú pre nás teraz zaujímavé:
Konštruktory
Okrem prázdneho List
u môžeme List
vytvoriť aj
ako kópiu z iného List
, poľa alebo inej kolekcie. Stačí
kolekciu odovzdať do konštruktora:
{CSHARP_CONSOLE}
string[] stringArray = {"First", "Second", "Third"};
List<string> l = new List<string>(stringArray);
Console.WriteLine(l[2]);
{/CSHARP_CONSOLE}
Kód vyššie vypíše "Third". Prvky poľa sa do nového hárka skopírujú. Rovnako môžeme odovzdať aj iný List.
Vlastnosti na liste
Count
- Funguje akoLength
na poli, vracia počet prvkov v kolekcii.
Metódy na liste
Add(položka)
- MetóduAdd()
sme si už vyskúšali, ako parameter berie položku, ktorú vloží na koniec listu.AddRange(kolekcia)
- Pridá do listu viac položiek, napr. z poľa.Clear()
- Vymaže všetky položky v liste.Contains(položka)
- Vraciatrue
/false
podľa toho, čiList
obsahuje odovzdanú položku.CopyTo(pole)
- Skopíruje položky do odovzdaného poľa. Môžeme pridať parameter štartovný index a počet prvkov.IndexOf(položka)
- Vráti index prvého výskytu položky (ako pri poli). Vracia-1
pri neúspechu.Insert(index, položka)
- Vloží položku na daný index (pozíciu) vList
u.InsertRange(index, kolekcia)
- Vloží prvky danej kolekcie na daný index vList
u.LastIndexOf(položka)
- Vracia index posledného výskytu položky vList
u. Vracia-1
pri neúspechu.Remove(položka)
- Vymaže prvú nájdenú položku.RemoveAt(index)
- Vymaže položku na danom indexe.RemoveRange(index, počet)
- Vymaže daný počet prvkov od zadaného indexu.Reverse()
- Funguje rovnako ako u poľa, obrátiList
tak, že je prvá položka posledná a naopak. Metóda nič nevracia, zmeny sa vykonajú priamo vList
.Sort()
-Sort()
už tiež poznáme, zotriedi položky v liste. Metóda opäť nič nevracia.ToArray()
- Skopíruje položky zList
u do poľa a to vráti.
Ďalšie metódy
List
poskytuje aj ďalšie metódy, ktoré poznáme z poľa:
Average()
- Vráti priemer z položiek vList
u akodouble
.Distinct()
- Vráti unikátne elementy zList
u.First()
- Vráti prvý element.Last()
- Vráti posledný element.Intersect(kolekcia)
- Vráti prienikList
so zadanou kolekciou.Union()
- Vráti zjednotenieList
u so zadanou kolekciou.Min()
- Vráti najmenší prvok.Max()
- Vráti najväčší prvok.Sum()
- Vráti súčet prvkov.Take(počet)
- Vráti prvky od začiatku kolekcieList
.
Vidíme, že kolekcia List
toho dokáže oveľa viac, než pole.
Najväčšou výhodou je pridávanie a mazanie prvkov. Daň vo výkone je
zanedbateľná. V kurze s kolekciami zistíme, že List
má ešte
ďalšie metódy, ale zatiaľ na to nemáme skúsenosti.
Program pre ukladanie žrebovaných čísel bol zaujímavý, ale určite sa nám bude v budúcnosti hodiť ukladať skôr objekty, než čísla.
V nasledujúcom cvičení, Riešené úlohy k 12.-13. lekciu OOP v C# .NET, 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é 2x (53.67 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#