12. díl - List ve Visual Basic .NET

Ostatní jazyky Visual Basic .NET Objektově orientované programování List ve Visual Basic .NET

V minulém dílu tutoriálů o VB.NET jsme si řekli něco o datu a času. Dnes si 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ána celá sekce. Dosud známe pouze kolekci pole. V průběhu seriálu 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 Integer, 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:

Dim cisla As List(Of Integer)

Datový typ píšeme u generických kolekcí do kulatých závorek za klíčové slovo Of. 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:

Dim cisla As List(Of Integer) = New List(Of Integer)

Takovýto list tedy umístíme do naší třídy, spolu s náhodným generátorem Random. Atributy inicializujeme v jejich deklaraci. Mohli bychom je inicializovat i v konstruktoru. Obě možnosti jsou správně, avšak obecně se doporučuje všechno inicializovat už v deklaraci, aby se předešlo výjimkám, kdy odkazujeme na neinicializovaný objekt.

Public Class Losovac
        Private cisla As List(Of Integer) = New List(Of Integer)
        Private random As Random = New Random()
End Class

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 dílu o hrací kostce, zde budeme vyhazovat čísla od 1 do 100. Číslo do Listu přidáme pomocí metody Add():

Public Function Losuj() As Integer
        Dim cislo As Integer = random.Next(100) + 1
        cisla.Add(cislo)
        Return cislo
End Function

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 Function Vypis() As String
        Dim s As String = ""
        cisla.Sort()
        For Each i As Integer In cisla
                s &= i & " "
        Next
        Return s
End Function

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 Character, nikoli jako String.

Dim losovac As New Losovac()
Console.WriteLine("Vítejte v programu losování.")
Dim volba As Char = "0"C
' hlavní cyklus
While volba <> "3"C
        ' 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
        Select Case volba
                Case "1"
                        Console.WriteLine("Padlo číslo: {0}", losovac.Losuj())
                Case "2"
                        Console.WriteLine("Padla čísla: {0}", losovac.Vypis())
                Case "3"
                        Console.WriteLine("Děkuji za použití programu")
                Case Else
                        Console.WriteLine("Neplatná volba, zadejte prosím znovu.")
        End Select
End While

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í Select Case a provedeme příslušné akce. Pokud bylo zadáno něco jiného, pokryje to možnost Case Else.

Losovač náhodných čísel v VB.NET pomocí Listu

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:

Dim l As New List(Of String)
l.Add("První")
Console.WriteLine(l(0))
l(0) = "První položka"
Console.WriteLine(l(0))
l(1) = "Druhá položka" ' vyhodí 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:

Dim poleStringu As String() = {"První", "Druha", "Třetí"}
Dim l As New List(Of 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(po­lož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(kolek­ce) - 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 sekci 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. Příště si uděláme pomocí Listu databázi, bude to elektronický diář! :)


 

  Aktivity (2)

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.

Jak se ti líbí článek?
Celkem (3 hlasů) :
55555


 



 

 

Komentáře
Zobrazit starší komentáře (3)

Avatar
Michal Žůrek (misaz):

ten kód funguje, opět tam ale není jedna, ale malé L. Jméno proměnné nemůže začínat číslem, proto je název 1 (jedna) nesmysl.

Odpovědět 3. července 10:06
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Michal Žůrek (misaz)
Jaroslav Trojan:

i když tam dám to malé l ,tak to hlásí stejnou chybu
jako předtím/ viz výše/

 
Odpovědět 3. července 15:45
Avatar
Jaroslav Trojan:

proč nejde tento kód:

Module Module1
Public jmeno As String
Public vek As Integer
Public heslo As String
Sub Main()
Dim u As New Uzivatel("Olda Novák", 87, "dům")
Dim a As New Administrator("Jar­da Trojan", 80, "bukovka")
'Dim u As Uzivatel = New Administrator("Jar­da Trojan", 80, "bukovka")
' u = a
' a = u
If TypeOf u Is Administrator Then
Console.Write­Line("je to administrator")
Else
Console.Write­Line("je to uživatel")
End If
Console.Write­Line(u)

Console.Write­Line(a)
Console.WriteLine()
' Uzivatel.Vypis(jme­no,vek,heslo)
Console.Write­Line(Uzivatel­.Vypis(jmeno, vek, heslo))
Console.ReadKey()
End Sub

End Module

třída Uzivatel

Public Class Uzivatel
Public jmeno As String
Public vek As Integer
Public heslo As String

Public Sub New(jmeno As String, vek As Integer, heslo As String)
Me.jmeno = jmeno
Me.vek = vek
Me.heslo = heslo
End Sub

Public Overrides Function ToString() As String
Return jmeno
Return vek
Return heslo
End Function
Public Function Vypis(jmeno, vek, heslo)
Console.Write­Line(jmeno, vek, heslo)
End Function

End Class

 
Odpovědět 3. července 16:14
Avatar
Odpovídá na Jaroslav Trojan
Michal Žůrek (misaz):
Dim poleStringu As String={"První","Druhá","Třetí"}
Dim l As New List(Of String) (poleStringu)
Console.WriteLine(l(2))

mě to funguje, otestoval jsem to. Podívej se jakou verzi .NET framework máš nastavenou při vytváření projektu. Je dost možné že starší verze něco z toho neumí. Práce s generickými kolekcemi se napříč verzemi trochu měnila.

Odpovědět 3. července 20:52
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Jaroslav Trojan
Michal Žůrek (misaz):

nemáš tam označený komentář Třída Uzivatel. Nikde tam nevidím třídu Administrator, kterou se snažíš používat. Metoda Uzivatel.Vypis je nesmysl. Třída Uzivatel nemá žádnou statickou metodu Vypis. Tu musíš volat na instanci, kterou chceš vypsat. Nějak zvláštně máš napsané WriteLine, když si to zkopíruju do notepad++ tak mi to tam z nějakého důvodu dosadí pomlčku Write-Line. Na úvod se podívej do místních tutoriálu OOP, tam najdeš odpovědi na vše co momentálně potřebuješ.

Odpovědět 3. července 20:59
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Michal Žůrek (misaz)
Michal Žůrek (misaz):

ups. Teď se dívám, že ten kód fakt nefunguje, protože tam chybí závorky definující že poleStringu je pole.

Dim poleStringu As String() = {"První", "Druhá", "Třetí"}
Dim l As New List(Of String)(poleStringu)
Console.WriteLine(l(2))
Editováno 3. července 21:02
Odpovědět 3. července 21:02
Nesnáším {}, proto se jim vyhýbám.
Avatar
 
Odpovědět 4. července 19:10
Avatar
Luboš Běhounek (Satik):

Mi někam zmizel komentář, by to chtělo nějakou zprávu typu "váš komentář byl smazán", takhle je to dost matoucí

Odpovědět 4. července 21:50
:)
Avatar
Adam Ježek
Tým ITnetwork
Avatar
Odpovídá na Luboš Běhounek (Satik)
Adam Ježek:

Přesunul sem to do fóra, tady ten kilometrovej kód neměl co dělat (jen se nějak nevybralo všechno, tak sem zbytek smazal, samotná reakce by tu nedávala smysl)

Odpovědět 5. července 8:36
Pokud chceš odpovědět, klikni na odpovědět. Pokud chceš vložit zdroják, klikni na vložit zdroják (</>)
Avatar
Jaroslav Trojan:

Ten první kód s Uživatel a Administrator je také vyřešen, viz lekce 14
Stačilo opravit funkce ToString() a Vypis() , pracuje to bezvadně

 
Odpovědět 8. července 12:55
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 13. Zobrazit vše