8. díl - Pole ve Visual Basicu

Ostatní jazyky Visual Basic .NET Základní konstrukce Pole ve Visual Basicu

Minule jsme si v našem Visual Basic seriálu ukázali ošetření uživatelských vstupů. Dnes si představíme datovou strukturu pole a vyzkoušíme si, co všechno umí.

Pole

Představte si, že si chcete uložit nějaké údaje o více prvcích. Např. chcete v paměti uchovávat 10 čísel, políčka šachovnice nebo jména 50ti uživatelů. Asi vám dojde, že v programování bude nějaká lepší cesta, než začít bušit proměnné uzivatel1, uzivatel2... až uzivatel50. Nehledě na to, že jich může být třeba 1000. A jak by se v tom potom hledalo? Brrr, takle ne :)

Pokud potřebujeme uchovávat větší množství proměnných stejného typu, tento problém nám řeší pole. Můžeme si ho představit jako řadu přihrádek, kde v každé máme uložený jeden prvek. Přihrádky jsou očíslované tzv. indexy, první má index 0.

Struktura pole

(Na obrázku je vidět pole osmi čísel)

Programovací jazyky se velmi liší v tom, jak s polem pracují. V některých jazycích (zejména starších, kompilovaných) nebylo možné za běhu programu vytvořit pole s dynamickou velikostí (např. mu dát velikost dle nějaké proměnné). Pole se muselo deklarovat s konstantní velikostí přímo ve zdrojovém kódu. Toto se obcházelo tzv. pointery a vlastními datovými strukturami, což často vedlo k chybám při manuální správě paměti a nestabilitě programu (např. v C++). Naopak některé interpretované jazyky umožňují nejen deklarovat pole s libovolnou velikostí, ale dokonce tuto velikost na již existujícím poli měnit (např. PHP). My víme, že VB.NET je virtuální stroj, tedy cosi mezi kompilerem a interpretem. Proto můžeme pole založit s velikostí, kterou dynamicky zadáme až za běhu programu, ale velikost existujícího pole modifikovat nemůžeme. Lze to samozřejmě obejít nebo použít jiné datové struktury, ale k tomu se dostaneme.

Možná vás napadá, proč se tu zabýváme s polem, když má evidentně mnoho omezení a existují lepší datové struktury. Odpověď je prostá: pole je totiž jednoduché. Nemyslím pro nás na pochopení (to také), ale zejména pro Visual Basic. Rychle se s ním pracuje, protože prvky jsou v paměti jednoduše uloženy za sebou, zabírají všechny stejně místa a rychle se k nim přistupuje. Mnoho vnitřních funkčností v .NET proto nějak pracuje s polem nebo pole vrací. Je to klíčová struktura.

Pro hromadnou manipulaci s prvky pole se používají cykly.

Pole deklarujeme pomocí kulatých závorek závorek:

Dim pole(9) As Integer

Pole je samozřejmě název naší proměnné. Nyní deklarovali, že v proměnné bude pole 10 Integerů. Pole se založí automaticky, pokud zadáme počet prvků v poli. Nyní máme v proměnné pole pole o velikosti 10 Integerů. Pozor na skutečnost, že jako délku zadáváme poslední index, který je číslovaný od nuly, pole(9) má tedy 10 prvků.

K prvkům pole potom přistupujeme přes kulatou závorku, pojďme na první index (tedy index 0) uložit číslo 1.

Dim pole(9) As Integer
pole(0) = 1

Plnit pole takhle ručně by bylo příliš pracné, použijeme cyklus a naplníme si pole čísly od 1 do 10. K naplnění použijeme for cyklus:

Dim pole(9) As Integer
For i = 0 To 9
        pole(i) = i + 1
Next

Abychom pole vypsali, můžeme za předchozí kód připsat:

For i = 0 To pole.Length - 1
        Console.Write("{0} ", pole(i))
Next

Všimněte si, že pole má vlastnost Length, kde je uložena jeho délka, tedy počet prvků.

Naplnění a výpis pole ve Visual Basic .NET

Můžeme použít zjednodušenou verzi cyklu pro práci s kolekcemi, známou jako For Each. Ten projede všechny prvky v poli a jeho délku si zjistí sám. Jeho syntaxe je následující:

For Each promenna As Integer In pole
        Console.WriteLine(promenna)
Next

Cyklus projede prvky v kolekci (to je obecný název pro struktury, které obsahují více prvků, u nás to bude pole) postupně od prvního do posledního. Prvek máme v každé iteraci cyklu uložený v dané proměnné.

Přepišme tedy náš dosavadní program pro For Each. For Each nemá řídící proměnnou, není tedy vhodný pro vytvoření našeho pole a použijeme ho jen pro výpis.

Dim pole(9) As Integer
pole(0) = 1
For i = 0 To 9
    pole(i) = i + 1
Next
For Each promenna In pole
    Console.Write("{0} ", promenna)
Next
Console.ReadKey()

Výstup programu:

1 2 3 4 5 6 7 8 9 10

Pole samozřejmě můžeme naplnit ručně a to i bez toho, abychom dosazovali postupně do každého indexu. Použijeme k tomu složených závorek a prvky oddělujeme čárkou:

Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Meggie"}

Všimněte si, že v tomto případě jsme nemuseli uvést počet prvků.

Pole často slouží k ukládání mezivýsledků, které se potom dále v programu používají. Když něco potřebujeme 10x, tak to nebudeme 10x počítat, ale spočítáme to jednou a uložíme do pole, odtud poté výsledek jen načteme.

Metody na třídě Array

.NET nám poskytuje třídu Array, která obsahuje pomocné metody pro práci s poli. Pojďme se na ně podívat:

Sort

Jak již název napovídá, metoda nám pole seřadí. Její jediný parametr je pole, které chceme seřadit. Je dokonce tak chytrá, že pracuje podle toho, co máme v poli uložené. Stringy třídí podle abecedy, čísla podle velikosti. Zkusme si seřadí a vypsat naši rodinku Simpsnů:

Dim simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Meggie"}
Array.Sort(simpsonovi)
For Each s As String In simpsonovi
        Console.Write("{0} ", s)
Next
Console.ReadKey()
Třídění/seřazení pole ve Visual Basic .NET

Zkuste si udělat pole čísel a vyzkoušejte si, že to opravdu funguje i pro ně.

Reverse

Reverse nám pole otočí (první prvek bude jako poslední atd.), toho můžeme využít např. pro třídění pozpátku:

Dim simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Meggie"}
Array.Sort(simpsonovi)
Array.Reverse(simpsonovi)
For Each s As String In simpsonovi
    Console.Write("{0} ", s)
Next
Console.ReadKey()

IndexOf a LastIndexOf

Tyto metody vrátí index prvního nebo posledního nalezeného prvku. V případě nenalezení prvku vrátí -1. Metoda bere dva parametry, prvním je pole, druhým hledaný prvek. Umožníme uživateli zadat jméno Simpsna a řekneme mu, na jaké pozici je uložený. Teď to pro nás nemá hlubší význam, protože prvek pole je jen String. Bude se nám to však velmi hodit ve chvíli, kdy v poli budeme mít uloženy plnohodnotné objekty. Berme to tedy jako takovou přípravu.

Dim simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Meggie"}
Console.WriteLine("Ahoj, zadej svého oblíbeného Simpsna (z rodiny Simpsnů): ")
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} nejoblíbenější simpson.", pozice + 1)
Else
    Console.WriteLine("Hele, tohle není simpson")
End If
Console.ReadKey()
Vyhledání prvků v poli ve Visual Basic .NET

Copy

Copy již podle názvu zkopíruje část pole do jiného pole. Prvním parametrem je zdrojové pole, druhým cílové a třetím počet znaků, který se má zkopírovat.

Metody na poli

Třída Array není jedinou možností, jak s polem manipulovat. Přímo na samotné instanci pole (konkrétní proměnné) můžeme volat také spoustu metod. I když si zmíníme jen některé, je jich opravdu hodně. Nebudeme tedy dělat příklady, jen si je popíšeme:

Length

Length jsme si již zmínili, vrátí délku pole. Není metodou, ale vlastností, nepíší se za ni tedy závorky ().

Min, Max, Average, Sum

Matematické metody, vracející nejmenší prvek (Min()), největší prvek (Max()), průměr ze všech prvků (Average()) a součet všech prvků (Sum()). Metody nemají žádné parametry.

Concat, Intersect, Union

Všechny tyto metody vrátí na výstupu nové pole a jako parametr mají druhé pole. Concat vykoná nám již známou konkatenaci, tedy k našemu poli připojí druhé pole a takto vzniklé nové pole vrátí. Intersect vykoná průnik obou polí, tedy sestaví pole s prvky, které jsou oboum polím společné. Union naopak vykoná sjednocení, funguje tedy podobně jako concat, jen prvky, které byly v obou polích, jsou v novém poli jen jednou.

First a Last

Již podle názvu metody vrátí první a poslední prvek, neberou žádné parametry.

Take a Skip

Obě tyto metody berou jako parametr počet prvků. Take vrátí pole s daným počtem prvků zkopírovaných od začátku původního pole. Skip naopak vrátí pole bez těchto prvních prvků.

Contains

Metoda vrací True/False podle toho, zda se prvek, uvedený v parametru metody, v daném poli nachází.

Reverse

Metodu Reverse známe již z třídy Array, pokud ji ale voláme na konkrétním poli, tak se prvky v něm neotočí, nýbrž je vytvořeno nové otočené pole a to je vráceno. Metoda nemá žádné parametry.

Distinct

Distinct je metoda bez parametrů a zajistí, aby byl v poli každý prvek jen jednou, tedy vymaže duplicitní prvky a unikátní pole vrátí jako návratovou hodnotu metody, opět tedy nemodifikuje dané pole.

Mnoho metod nemění přímo naše pole, ale vrátí pouze pole nové (jsou to metody Concat, Intersect, Union, Reverse a Distinct), ve kterém jsou provedeny požadované změny. Pokud chceme modifikovat původní pole, musíme do něj takto dosadit. Tyto metody bohužel z důvodů, které pochopíme až později, nevrací přímo pole, ale typ IEnumerable. Aby bylo dosazení výsledku zpět do pole možné, musíme ho ještě převést na pole metodou ToArray().

Dim cisla = { 1, 2, 3, 3, 3, 5 }
cisla = cisla.Distinct().ToArray()

Proměnná délka pole

Říkali jsme si, že délku pole můžeme definovat i za běhu programu, pojďme si to zkusit a rovnou si vyzkoušejme nějakou metodu na poli:

Console.WriteLine("Ahoj, spočítám ti průměr známek. Kolik známek zadáš?")
Dim pocet As Integer = Console.ReadLine()
Dim cisla(pocet) As Integer
For i = 0 To pocet - 1
        Console.Write("Zadejte {0}. číslo: ", i + 1)
        cisla(i) = Console.ReadLine()
Next
Console.WriteLine("Průměr tvých známek je: {0}", cisla.Average())
Console.ReadKey()
Proměnná délka pole ve Visual Basic .NET

Tento příklad by šel samozřejmě napsat i bez použití pole, ale co kdybychom chtěli spočítat např. medián? Nebo např. vypsat zadaná čísla pozpátku? To už by bez pole nešlo. Takhle máme k dispozici v poli původní hodnoty a můžeme s nimi neomezeně a jednoduše pracovat.

To by pro dnešek stačilo, můžete si s polem hrát. Příště na vás čeká překvapení ;-)


 

  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 (2 hlasů) :
55555


 



 

 

Komentáře

Avatar
Libor Šimo (libcosenior):

Tu máš chybičku:

Dim pole(4) As Integer
pole(0) = 1
For i = 1 To 4
        pole(i) = i
Next

Takto by to malo byť:

Dim pole(4) As Integer
' pole(0) = 1
For i = 1 To 5
     pole(i - 1) = i
Next
Odpovědět 14.7.2013 21:22
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):

Aj tu je jedna:

For i = 0 To pole.Length - 1
        Console.Write("{0} ", pole[i])
Next

pole[i] by fungovalo napr. v c#, c alebo c++, ale tu nie. :`

Odpovědět 14.7.2013 21:27
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Libor Šimo (libcosenior)
Michal Žůrek (misaz):

jasně ten řádek tam je zbytečný a cykl nemá začínat jedničkou ale nulou.

si asi první kdo to čte :D . na index v poli se dostaneš pomocí kulatých závorek ne hranatých. Díky chyby opravím.

Odpovědět 14.7.2013 21:39
Nesnáším {}, proto se jim vyhýbám.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Michal Žůrek (misaz)
Kit:

Stejně je divné mít pole indexované od nuly. Fortran to má vyřešené lépe. Můžeš si vybrat, jestli od nuly, od jedné (default) nebo od jiného čísla (třeba i záporného). Nevšiml jsem si, že by měl někdo problém s polem, které začínalo od jedné. V Pascalu totéž.

Odpovědět 14.7.2013 21:51
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Michal Žůrek (misaz):

ono si můžeš zde třeba implementovat vlastní pole nebo kolekci a dát mu vlastní číslování indexů. To není až zas takový problém.

Ale spíš upřímně. Kdo by plýtval časem a znovu vymýšlel kolo (pole)?

Odpovědět  +1 14.7.2013 21:55
Nesnáším {}, proto se jim vyhýbám.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Michal Žůrek (misaz)
Kit:

Samozřejmě je jednodušší se přizpůsobit. Stejně se to pole většinou zavře někam do objektu a pak už je jedno, jaké má uvnitř indexování. Ven není vidět, tak se to nedá ani splést.

Odpovědět 14.7.2013 22:03
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Ondrej_d
Člen
Avatar
Ondrej_d:

Dovolim si opravit priemer znamok:

Console.Write­Line("Ahoj, spočítám ti průměr známek. Kolik známek zadáš?")
Dim pocet As Integer = Console.ReadLine()
Dim cisla(pocet - 1) As Integer
For i = 0 To (pocet - 1)
Console.Write("Za­dejte {0}. číslo: ", i + 1)
cisla(i) = Console.ReadLine()
Next
Console.Write­Line("Průměr tvých známek je: {0}", cisla.Average())
Console.ReadKey()

kedze 10 znamek znamena 11 vstupov

 
Odpovědět 24.2.2015 19:33
Avatar
Jaroslav Trojan:

pole simpsonovi() se nedá naplnit jmény, protože jména červeně podtrhne a hlásí error: String se nedá konvertovat na String , tak co s tím? Díky!

 
Odpovědět 8. června 9:57
Avatar
Jaroslav Trojan:

Dim simpsonovi() As String=("Homer", "Merge", ...atd )
Jména podtrhuje červeně a hlásí error

 
Odpovědět 8. června 10:02
Avatar
Odpovídá na Jaroslav Trojan
Michal Žůrek (misaz):

patří tam složené závorky, ne kulaté.

Dim simpsonovi() As String = {"Homer", "Marge", "Bart", "Lisa", "Meggie"}
Odpovědět  +1 8. června 20:07
Nesnáším {}, proto se jim vyhýbám.
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 10.