Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 13 - List

V minulé lekci, Datum a čas v C# - DateOnly a TimeOnly, jsme si procvičili použití struktur DateOnly a TimeOnly.

Dnes si v C# tutoriálu ukážeme jednu kolekci, která je chytřejší, než pole. Umožňuje totiž prvky libovolně přidávat a mazat.

Pojem kolekce jsme tu již zmínili. Je to struktura, do které můžeme ukládat více objektů. Kolekcí je v .NET frameworku velké množství, jsou uzpůsobeny pro různé účely a můžeme s nimi zacházet různými způsoby. Proto jim je věnován i celý kurz Kolekce a LINQ. Dosud známe pouze kolekci pole. V průběhu kurzu však budeme potřebovat něco chytřejšího, kam budeme moci jednoduše za běhu programu přidávat a mazat záznamy. Jistě by se nám hodilo si v paměti spravovat databázi nějakých objektů. Víme, že pole má konstantní velikost, což je daň za jeho vysokou rychlost. Nyní si představíme List, který můžeme chápat jako nadstavbu pole.

List

List je tzv. generická kolekce. Pojem genericita si plně vysvětlíme až u kolekcí, nyní nám bude stačit vědět, že při deklaraci Listu musíme specifikovat datový typ objektů, které v něm budou uloženy. Začněme jednoduše a udělejme si List čísel, která budeme náhodně losovat.

Losování

Program se nás vždy zeptá, zda chceme losovat další číslo a to se přidá do Listu. Pokud již nebudeme chtít losovat, program vypíše losovaná čísla, seřazená od nejmenšího po největší. Založme si nový projekt Losovani a vytvořme si třídu Losovac. Třída bude obsahovat List typu int, kde budou čísla uložena. List bude privátní a bude sloužit pouze jako interní úložiště dané třídy, aby se na něj zvenku nedalo přistupovat. List deklarujeme takto:

List<int> cisla;

Datový typ píšeme u generických kolekcí do špičatých závorek. List je samozřejmě objekt, jako každý jiný. Stejně jako u pole a jiných objektů, i zde proměnnou před použitím inicializujeme:

List<int> cisla = new List<int>();

Všimněte si závorek, které značí konstruktor. Takovýto list tedy umístíme do naší třídy, spolu s náhodným generátorem Random. V konstruktoru atributy inicializujeme:

class Losovac
{
    private List<int> cisla;
    private Random random;

    public Losovac()
    {
        random = new Random();
        cisla = new List<int>();
    }

}

Dále přidáme metody Losuj() a Vypis(), kde Losuj() přidá do Listu nové náhodné číslo a také ho vrátí jako návratovou hodnotu. Vypis() vrátí textový řetězec pro vypsání. Ten bude obsahovat čísla z cisla, seřazená a oddělená mezerou.

Losování náhodného čísla již známe z lekce o hrací kostce, zde budeme vyhazovat čísla od 1 do 100. Číslo do Listu přidáme pomocí metody Add():

public int Losuj()
{
    int cislo = random.Next(100) + 1;
    cisla.Add(cislo);
    return cislo;
}

Velmi jednoduché, že? Kolekce List je interně poměrně složitá a zatím se nebudeme zabývat tím, co se uvnitř děje. To je ostatně účel .NET frameworku, nabízet kvalitní a sofistikované komponenty, které se jednoduše používají.

Výpis čísel bude ještě snazší. K setřídění použijeme metodu Sort() na Listu, která list setřídí. Je podobná metodě Sort() na třídě Array. Metoda nic nevrací, pouze List uvnitř setřídí.

public string Vypis()
{
    string s = "";
    cisla.Sort();
    foreach (int i in cisla)
        s += i + " ";
    return s;
}

Hotovo.

Přesuňme se do Main() a pomocí while cyklu umožněme uživateli ovládat objekt. Podobný program byla kalkulačka z prvních lekcí, kde jsme se v cyklu ptali, zda si uživatel přeje opakovat výpočet. Zde budeme postupovat totožně.

Ovládání bude pomocí možností 1, 2, 3 (losuj, vypiš, konec). Budeme je načítat pomocí Console.ReadKey() jako char, nikoli jako string. Nezapomeňte tedy, že znaky zapisujeme pomocí apostrofů, nikoli uvozovek.

Losovac losovac = new Losovac();
Console.WriteLine("Vítejte v programu losování.");
char volba = '0';
// hlavní cyklus
while (volba != '3')
{
    // výpis možností
    Console.WriteLine("1 - Losovat další číslo");
    Console.WriteLine("2 - Vypsat čísla");
    Console.WriteLine("3 - Konec");
    volba = Console.ReadKey().KeyChar;
    Console.WriteLine();
    // reakce na volbu
    switch (volba)
    {
        case '1':
            Console.WriteLine("Padlo číslo: {0}", losovac.Losuj());
            break;
        case '2':
            Console.WriteLine("Padla čísla: {0}", losovac.Vypis());
            break;
        case '3':
            Console.WriteLine("Děkuji za použití programu");
            break;
        default:
            Console.WriteLine("Neplatná volba, zadejte prosím znovu.");
            break;
    }
}

Průběh programu je z kódu dobře viditelný. Nejprve nastavíme volbu na nějakou výchozí hodnotu, aby cyklus poprvé proběhl. Poté volbu načteme z klávesnice jako znak. Znak zpracujeme pomocí switche a provedeme příslušné akce. Pokud bylo zadáno něco jiného, pokryje to možnost default:.

Konzolová aplikace
3 - Konec
1
Padlo číslo: 52
1 - Losovat další číslo
2 - Vypsat čísla
3 - Konec
1
Padlo číslo: 40
1 - Losovat další číslo
2 - Vypsat čísla
3 - Konec
1
Padlo číslo: 62
1 - Losovat další číslo
2 - Vypsat čísla
3 - Konec
2
Padla čísla: 2 6 7 7 8 8 9 9 10 10 12 14 17 19 19 21 23 25 25 27 27 27 28 28 28 30 30 31 32 33 33 35 35 36 36 36 37 38 38 40 41 42 42 42 44 45 45 45 45 45 48 51 52 52 53 55 56 56 56 57 58 58 59 61 62 66 68 68 71 72 73 73 74 76 82 83 84 84 85 87 88 88 89 90 90 91 93 94 98 98 98 99 100
1 - Losovat další číslo
2 - Vypsat čísla
3 - Konec

Vidíme, že můžeme stále přidávat nová a nová čísla. Máme mnohem větší možnosti, než s polem. Zároveň však můžeme s Listem pracovat úplně stejně, jako jsme pracovali s polem.

Můžeme používat indexaci pomocí hranatých závorek, ale pozor, prvek musí existovat. Zkusme si napsat následující kód:

List<string> l = new List<string>();
l.Add("První");
Console.WriteLine(l[0]);
l[0] = "První položka";
Console.WriteLine(l[0]);
l[1] = "Druhá položka";  // způsobí chybu

Vytvoříme si List stringů. Přidáme položku "První" a poté vypíšeme položku na indexu 0. Vypíše se nám "První". Můžeme na ni samozřejmě i takto zapisovat. S druhou položkou na pozici 1 však již nemůžeme pracovat, protože jsme ji do listu nepřidali. U pole jsme zadali velikost a on všechny "přihrádky" (proměnné pod indexy) založil. Nyní velikost nezadáváme a "přihrádky" si přidáváme sami.

Podívejme se na List podrobněji a vypišme si metody, které jsou pro nás nyní zajímavé:

Konstruktory

Kromě prázdného Listu můžeme List vytvořit i jako kopii z jiného Listu, pole nebo jiné kolekce. Stačí kolekci předat do konstruktoru:

string[] poleStringu = {"První", "Druha", "Třetí"};
List<string> l = new List<string>(poleStringu);
Console.WriteLine(l[2]);

Kód výše vypíše "Třetí". Prvky pole se do nového listu zkopírují. Stejně můžeme předat i jiný List.

Vlastnosti na listu

  • Count - Funguje jako Length na poli, vrací počet prvků v kolekci.

Metody na listu

  • Add(položka) - Metodu Add() jsme si již vyzkoušeli, jako parametr bere položku, kterou vloží na konec listu.
  • AddRange(kolekce) - Přidá do listu více položek, např. z pole.
  • Clear() - Vymaže všechny položky v listu.
  • Contains(položka) - Vrací true/false podle toho, zda List obsahuje předanou položku.
  • CopyTo(pole) - Zkopíruje položky do předaného pole. Můžeme přidat parametr startovní index a počet prvků.
  • IndexOf(položka) - Vrátí index prvního výskytu položky (jako u pole). Vrací -1 při neúspěchu.
  • Insert(index, položka) - Vloží položku na daný index (pozici) v Listu.
  • InsertRange(index, kolekce) - Vloží prvky dané kolekce na daný index v Listu.
  • LastIndexOf(položka) - Vrací index posledního výskytu položky v Listu. Vrací -1 při neúspěchu.
  • Remove(položka) - Vymaže první nalezenou položku.
  • RemoveAt(index) - Vymaže položku na daném indexu.
  • RemoveRange(index, počet) - Vymaže daný počet prvků od zadaného indexu.
  • Reverse() - Funguje stejně jako u pole, obrátí List tak, že je první položka poslední a naopak. Metoda nic nevrací, změny se provedou přímo v Listu.
  • Sort() - Sort() již také známe, setřídí položky v listu. Metoda opět nic nevrací.
  • ToArray() - Zkopíruje položky z Listu do pole a to vrátí.

Další metody

List poskytuje i další metody, které známe z pole:

  • Average() - Vrátí průměr z položek v Listu jako double.
  • Distinct() - Vrátí unikátní elementy z Listu.
  • First() - Vrátí první element.
  • Last() - Vrátí poslední element.
  • Intersect(kolekce) - Vrátí průnik Listu se zadanou kolekcí.
  • Union() - Vrátí sjednocení Listu se zadanou kolekcí.
  • Min() - Vrátí nejmenší prvek.
  • Max() - Vrátí největší prvek.
  • Sum() - Vrátí součet prvků.
  • Take(počet) - Vrátí prvky od začátku Listu.

Vidíme, že kolekce List toho umí mnohem více, než pole. Největší výhodou je přidávání a mazání prvků. Daň ve výkonu je zanedbatelná. V kurzu s kolekcemi zjistíme, že List má ještě další metody, ale zatím na to nemáme zkušenosti.

Program pro ukládání losovaných čísel byl zajímavý, ale jistě se nám bude v budoucnu hodit ukládat spíše objekty, než čísla.

V následujícím cvičení, Řešené úlohy k 12.-13. lekci OOP v C# .NET, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 909x (26.67 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Datum a čas v C# - DateOnly a TimeOnly
Všechny články v sekci
Objektově orientované programování v C# .NET
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 12.-13. lekci OOP v C# .NET
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
381 hlasů
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 se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity