Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.
IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

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:

string[] stringArray = {"First", "Second", "Third"};
List<string> l = new List<string>(stringArray);
Console.WriteLine(l[2]);

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 ako Length na poli, vracia počet prvkov v kolekcii.

Metódy na liste

  • Add(položka) - Metódu Add() 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) - Vracia true / false podľa toho, či List 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) v List u.
  • InsertRange(index, kolekcia) - Vloží prvky danej kolekcie na daný index v List u.
  • LastIndexOf(položka) - Vracia index posledného výskytu položky v List 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áti List tak, že je prvá položka posledná a naopak. Metóda nič nevracia, zmeny sa vykonajú priamo v List.
  • Sort() - Sort() už tiež poznáme, zotriedi položky v liste. Metóda opäť nič nevracia.
  • ToArray() - Skopíruje položky z List 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 v List u ako double.
  • Distinct() - Vráti unikátne elementy z List u.
  • First() - Vráti prvý element.
  • Last() - Vráti posledný element.
  • Intersect(kolekcia) - Vráti prienik List so zadanou kolekciou.
  • Union() - Vráti zjednotenie List 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 kolekcie List.

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#

 

Predchádzajúci článok
Dátum a čas v C# - DateOnly a TimeOnly
Všetky články v sekcii
Objektovo orientované programovanie v C# .NET
Preskočiť článok
(neodporúčame)
Riešené úlohy k 12.-13. lekciu OOP v C# .NET
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
1 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity