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

Zoznam (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 zoznamu 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 zoznamu. 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 zoznam 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 zoznamu numbers 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 kolekcie List 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() volanú na inštanciu zoznamu, 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
You got a: 40
1 - Lot the next number
2 - Print numbers
3 - Quit
1
You got a: 62
1 - Lot the next number
2 - Print numbers
3 - Quit
2
Numbers drawn: 10 12 13 14 21 22 23 24 28 28 40 42 45 52 52 57 58 59 62 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 so zoznamom 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 položiek typu 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 zoznamu 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 zoznamu môžeme List vytvoriť aj ako kópiu z iného zoznamu, 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 zoznamu skopírujú. Rovnako môžeme odovzdať aj iný List.

Vlastnosti kolekcie List

  • Count - Funguje ako Length na poli, vracia počet prvkov v kolekcii.

Metódy kolekcie List

  • Add(item) - Metódu Add() sme si už vyskúšali, ako parameter berie položku, ktorú vloží na koniec zoznamu.
  • AddRange(collection) - Pridá do zoznamu viac položiek, napr. z poľa.
  • Clear() - Vymaže všetky položky v zoznamu.
  • Contains(item) - Vracia true / false podľa toho, či List obsahuje odovzdanú položku.
  • CopyTo(array) - Skopíruje položky do odovzdaného poľa. Môžeme pridať parameter štartovný index a počet prvkov.
  • IndexOf(item) - Vráti index prvého výskytu položky (ako pri poli). Vracia -1 pri neúspechu.
  • Insert(index, item) - Vloží položku na daný index (pozíciu) v zoznamu.
  • InsertRange(index, collection) - Vloží prvky danej kolekcie na daný index.
  • LastIndexOf(item) - Vracia index posledného výskytu položky. Vracia -1 pri neúspechu.
  • Remove(item) - Vymaže prvú nájdenú položku.
  • RemoveAt(index) - Vymaže položku na danom indexe.
  • RemoveRange(index, count) - 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 danom zoznamu.
  • Sort() - Sort() už tiež poznáme, zotriedi položky v zoznamu. Metóda opäť nič nevracia.
  • ToArray() - Skopíruje položky 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 ako double.
  • Distinct() - Vráti unikátne elementy.
  • First() - Vráti prvý element.
  • Last() - Vráti posledný element.
  • Intersect(collection) - Vráti prienik zoznamu so zadanou kolekciou.
  • Union(collection) - Vráti zjednotenie `zoznamu so zadanou kolekciou.
  • Min() - Vráti najmenší prvok.
  • Max() - Vráti najväčší prvok.
  • Sum() - Vráti súčet prvkov.
  • Take(count) - 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. lekcii 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é 4x (55.91 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. lekcii 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