8. diel - Poľa vo Visual Basicu
V minulej lekcii, Ošetrenie užívateľských vstupov , sme si ukázali ošetrenie užívateľských vstupov. V dnešnom VB.NET tutoriálu si predstavíme dátovú štruktúru poľa a vyskúšame si, čo všetko vie.
Poľa
Predstavte si, že si chcete uložiť nejaké údaje o viac prvkoch. Napr.
chcete v pamäti uchovávať 10 čísel, políčka šachovnice alebo mena 50tich
užívateľov. Asi vám dôjde, že v programovaní bude nejaká lepšia cesta,
než začať búšiť premenné Užívateľ 1
,
Užívateľ 2
... až uzivatel50
.
Nehľadiac na to, že ich môže byť potrebné 1000. A ako by sa v tom potom
hľadalo? Brrr, takto nie
Ak potrebujeme uchovávať väčšie množstvo premenných rovnakého
typu, tento problém nám rieši poľa. Môžeme si ho predstaviť ako
rad priehradiek, kde v každej máme uložený jeden prvok. Priehradky sú
očíslované tzv. indexy
, prvý má index 0
.
(Na obrázku je vidieť pole ôsmich čísiel)
Programovacie jazyky sa veľmi líšia v tom, ako s poľom pracujú. V niektorých jazykoch (najmä starších, kompilovaných) nebolo možné za behu programu vytvoriť pole s dynamickou veľkosťou (napr. Mu dať veľkosť podľa nejaké premenné). Pole sa muselo deklarovať s konštantnou veľkosťou priamo v zdrojovom kóde. Toto sa obchádzalo tzv. Pointer a vlastnými dátovými štruktúrami, čo často viedlo k chybám pri manuálnej správe pamäte a nestabilite programu (napr. V C ++). Naopak niektoré interpretované jazyky umožňujú nielen deklarovať pole s ľubovoľnou veľkosťou, ale dokonca túto veľkosť na už existujúcom poli meniť (napr. PHP). My vieme, že VB.NET je virtuálny stroj, teda čosi medzi kompilerem a interpretom. Preto môžeme pole založiť s veľkosťou, ktorú dynamicky zadáme až za behu programu, ale veľkosť existujúceho poľa modifikovať nemôžeme. Možno to samozrejme obísť alebo použiť iné dátové štruktúry, ale k tomu sa dostaneme.
Možno vás napadá, prečo sa tu zaoberáme s poľom, keď má evidentne veľa obmedzení a existujú lepšie dátové štruktúry. Odpoveď je prostá: poľa je totiž jednoduché. Nemyslím pre nás na pochopenie (to tiež), ale najmä pre Visual Basic. Rýchlo sa s ním pracuje, pretože prvky sú v pamäti jednoducho uložené za sebou, zaberajú všetky rovnako miesta a rýchlo sa k nim pristupuje. Mnoho vnútorných funkčnosťou v .NET preto nejako pracuje s poľom alebo poľa vracia. Je to kľúčová štruktúra.
Pre hromadnú manipuláciu s prvkami poľa sa používajú cykly.
Pole deklarujeme pomocou okrúhlych zátvoriek:
Dim pole(9) As Integer
Slovo pole
je samozrejme názov našej premennej. Teraz sme
deklarovali, že v premennej bude pole 10 prvkov typu Integer
. Pole
sa založí automaticky, ak zadáme počet prvkov v poli. Teraz máme v
premennej pole
poľa veľkosti 10 čísel typu
Integer
. Pozor na skutočnosť, že ako dĺžku zadávame
posledný index, ktorý je číslovaný od nuly, pole(9)
má teda
10
prvkov.
K prvkom poľa potom pristupujeme cez okrúhlu zátvorku, poďme na prvý
index (teda index 0
) uložiť číslo 1
.
Dim pole(9) As Integer pole(0) = 1
Plniť pole takhle ručne by bolo príliš pracné, použijeme cyklus a
naplníme si pole číslami od 1
do 10
. K naplneniu
použijeme For
cyklus:
Dim pole(9) As Integer For i As Integer = 0 To 9 pole(i) = i + 1 Next
Aby sme pole vypísali, môžeme za predchádzajúci kód pripísať:
{VBNET_CONSOLE}
Dim pole(9) As Integer
For i As Integer = 0 To 9
pole(i) = i + 1
Next
For i As Integer = 0 To pole.Length - 1
Console.Write("{0} ", pole(i))
Next
{/VBNET_CONSOLE}
Všimnite si, že pole má vlastnosť Length
, kde je uložená
jeho dĺžka, teda počet prvkov.
Konzolová aplikácia
1 2 3 4 5 6 7 8 9 10
Môžeme použiť zjednodušenú verziu cyklu pre prácu s kolekciami, známu
ako For Each
. Ten prejde všetky prvky v poli a jeho dĺžku si
zistí sám. Jeho syntax je nasledujúca:
For Each premenna As Integer In poľa Console.WriteLine(premenna) Next
Cyklus prejde prvky v kolekcii (to je všeobecný názov pre štruktúry, ktoré obsahujú viac prvkov, u nás to bude údaj) postupne od prvého do posledného. Prvok máme v každej iterácii cyklu uložený v danej premennej.
Prepíšme teda náš doterajší program pre For Each
.
For Each
nemá riadiace premennú, nie je teda
vhodný pre vytvorenie nášho poľa a použijeme ho len pre výpis.
{VBNET_CONSOLE}
Dim pole(9) As Integer
pole(0) = 1
For i As Integer = 0 To 9
pole(i) = i + 1
Next
For Each promenna As Integer In pole
Console.Write("{0} ", promenna)
Next
Console.ReadKey()
{/VBNET_CONSOLE}
Výstup programu:
Konzolová aplikácia
1 2 3 4 5 6 7 8 9 10
Pole samozrejme môžeme naplniť ručne a to aj bez toho, aby sme dosadzovali postupne do každého indexu. Použijeme na to zložených zátvoriek a prvky oddeľujeme čiarkou:
Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Maggie"}
Všimnite si, že v tomto prípade sme nemuseli uviesť počet prvkov.
Pole často slúži na ukladanie medzivýsledkov, ktoré sa potom ďalej v programe používajú. Keď niečo potrebujeme 10x, tak to nebudeme 10x počítať, ale spočítame to raz a uložíme do poľa, odtiaľ potom výsledok len načítame.
Metódy na triede Array
.NET nám poskytuje triedu Array
, ktorá obsahuje pomocné
metódy pre prácu s poľami. Poďme sa na ne pozrieť:
Sort ()
Ako už názov napovedá, metóda nám poľa zoradí. Jej jediný parameter
je pole, ktoré chceme zoradiť. Je dokonca tak múdra, že pracuje podľa toho,
čo máme v poli uložené. Stringy
triedi podľa abecedy, čísla
podľa veľkosti. Skúsme si zoradí a vypísať našu rodinku Simpson:
{VBNET_CONSOLE}
Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Maggie"}
Array.Sort(simpsonovi)
For Each s As String In simpsonovi
Console.Write("{0} ", s)
Next
Console.ReadKey()
{/VBNET_CONSOLE}
Konzolová aplikácia
Bart Homer Lisa Maggie Marge
Skúste si urobiť polia čísel a vyskúšajte si, že to naozaj funguje aj pre nich.
Reverse ()
Reverse()
nám pole otočí (prvý prvok bude ako posledná
atď.), Toho môžeme využiť napr. Pre triedenie pospiatky:
{VBNET_CONSOLE}
Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Maggie"}
Array.Sort(simpsonovi)
Array.Reverse(simpsonovi)
For Each s As String In simpsonovi
Console.Write("{0} ", s)
Next
Console.ReadKey()
{/VBNET_CONSOLE}
IndexOf () a lastIndexOf ()
Tieto metódy vráti index prvého alebo posledného nájdeného prvku. V
prípade nenájdenia prvku vráti -1
. Metóda berie dva parametre,
prvým je pole, druhým hľadaný prvok. Umožníme užívateľovi zadať meno
Simpsons a povieme mu, na akej pozícii je uložený. Teraz to pre nás nemá
hlbší význam, pretože prvok poľa je len String
. Bude sa nám
to však veľmi hodiť vo chvíli, kedy v poli budeme mať uložené
plnohodnotné objekty. Berme to teda ako takú prípravu.
{VBNET_CONSOLE}
Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Maggie"}
Console.WriteLine("Ahoj zadaj svojho obľúbeného Simpsni (z rodiny Simpson): ")
Dim simpson As String = Console.ReadLine()
Dim pozice As Integer = Array.IndexOf(simpsonovi, simpson)
If pozice >= 0 Then
Console.WriteLine("Jo, to je môj {0}. najobľúbenejší Simpson!", pozice + 1)
Else
Console.WriteLine("Hele, toto nie je Simpson")
End If
Console.ReadKey()
{/VBNET_CONSOLE}
Konzolová aplikácia
Ahoj zadaj svojho obľúbeného Simpsni (z rodiny Simpsů):
Homer
Jo, to je môj 1. najobľúbenejší Simpson!
Copy ()
Copy()
už podľa názvu skopíruje časť poľa do iného
poľa. Prvým parametrom je zdrojové pole, druhým cieľové a tretím počet
znakov, ktorý sa má skopírovať.
Metódy na poli
Trieda Array
nie je jedinou možnosťou, ako s poľom
manipulovať. Priamo na samotné inštanciu pole (konkrétne premenné) môžeme
volať aj veľa metód. Aj keď si spomenieme len niektoré, je ich naozaj
veľa. Nebudeme teda robiť príklady, len si ich popíšeme:
Length
Length
sme si už spomenuli, vráti dĺžku poľa. Nie je
metódou, ale vlastností, nepíšu sa za ňu teda zátvorky
()
.
Min (), Max (), Average (), Sum ()
Matematické metódy, vracajúci najmenší prvok (Min()
),
najväčší prvok (Max()
), priemer zo všetkých prvkov
(Average()
) a súčet všetkých prvkov (Sum()
).
Metódy nemajú žiadne parametre.
Concat (), Intersect (), Union ()
Všetky tieto metódy vráti na výstupe nové pole a ako parameter majú
druhé pole. Concat()
vykoná nám už známu konkatenaci, teda k
nášmu poli pripojí druhé pole a takto vzniknuté nové pole vráti.
Intersect()
vykoná prienik oboch polí, teda zostaví pole s
prvkami, ktoré sú obom poliam spoločné. Union()
naopak vykoná
zjednotenie, funguje teda podobne ako Concat()
, len prvky, ktoré
boli v oboch poliach, sú v novom poli len raz.
First () a Last ()
Už podľa názvu metódy vráti prvý a posledný prvok, neberú žiadne parametre.
Take () a Skip ()
Obe tieto metódy berú ako parameter počet prvkov. Take vráti pole s
daným počtom prvkov skopírovaných od začiatku pôvodného poľa.
Skip()
naopak vráti pole bez týchto prvých prvkov.
Contains ()
Metóda vracia True
/ False
podľa toho, či sa
prvok, uvedený v parametri metódy, v danom poli nachádzajú.
Reverse ()
Metódu Reverse()
poznáme už z triedy Array
,
pokiaľ ju ale voláme na konkrétnom poli, tak sa prvky v ňom neotočí, ale
je vytvorené nové otočené poľa a to je vrátený. Metóda nemá žiadne
parametre.
Distinct ()
Distinct()
je metóda bez parametrov a zabezpečí, aby bol v
poli každý prvok len raz, teda vymaže duplicitné prvky a unikátne pole
vráti ako návratovú hodnotu metódy, opäť teda nemodifikuje dané pole.
Mnoho metód nemení priamo naše polia, ale vráti iba polia nové (sú to
metódy Concat()
, Intersect()
, Union()
,
Reverse()
a Distinct()
), v ktorom sú vykonané
požadované zmeny. Ak chceme modifikovať pôvodné pole, musíme doň takto
dosadiť. Tieto metódy bohužiaľ z dôvodov, ktoré pochopíme až neskôr,
nevracia priamo pole, ale typ IEnumerable
. Aby bolo dosadení
výsledku späť do poľa možné, musíme ho ešte previesť na pole metódou
ToArray()
.
Dim cisla() = { 1, 2, 3, 3, 3, 5 } cisla = cisla.Distinct().ToArray()
Premenná dĺžka poľa
Hovorili sme si, že dĺžku poľa môžeme definovať aj za behu programu, poďme si to skúsiť a rovno si vyskúšajme nejakú metódu na poli:
Console.WriteLine("Ahoj, spočítám ti priemer známok. Koľko známok zadáš?") Dim pocet As Integer = Console.ReadLine() Dim cisla(pocet - 1) As Integer For i As Integer = 0 To pocet - 1 Console.Write("Zadajte {0}. číslo: ", i + 1) cisla(i) = Console.ReadLine() Next Console.WriteLine("Priemer tvojich známok je: {0}", cisla.Average()) Console.ReadKey()
Konzolová aplikácia
Ahoj, spočítám ti priemer známok. Koľko známok zadáš?
5
Zadajte 1. číslo: 1
Zadajte 2. číslo: 2
Zadajte 3. číslo: 2
Zadajte 4. číslo: 3
Zadajte 5. číslo: 5
Priemer tvojich známok je: 2,6
Tento príklad by išiel samozrejme napísať aj bez použitia poľa, ale čo keby sme chceli spočítať napr. Medián? Alebo napr. Vypísať zadané čísla pospiatky? To už by bez poľa nešlo. Takto máme k dispozícii v poli pôvodnej hodnoty a môžeme s nimi neobmedzene a jednoducho pracovať.
To by pre dnešok stačilo, môžete si s poľom hrať. V budúcej lekcii, Riešené úlohy k 8. lekcii VB.NET , na vás čaká prekvapenie
V nasledujúcom cvičení, Riešené úlohy k 8. lekcii VB.NET, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.