7. diel - Poľa vo Swift
V minulej lekcii kurzu, Typový systém: Optionals vo Swift , sme sa naučili používať Optionals. Dnes si vo Swift tutoriálu 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 50
užívateľov. Asi vám dôjde, že v programovaní bude nejaká lepšia cesta,
než začať búšiť premenné uzivatel1
,
uzivatel2
... 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). Swift k poliam pristupuje pomerne moderne. Nerieši veľkosť (ani ju nemôžete pevne zadať) a pre pridávanie prvkov sa používa metóda, takže nemusíte riešiť indexy. Tomuto typu kolekcia (kontajnerové štruktúry) sa v niektorých jazykoch hovorí skôr zoznam, než polia. Swift ho však ako pole označuje. Pre hromadnú manipuláciu s prvkami poľa sa používajú cykly.
Pole deklarujeme pomocou hranatých zátvoriek a obyčajných zátvoriek:
var pole = [Int]()
Výraz pole
je samozrejme názov našej premennej.
K prvkom poľa potom pristupujeme cez hranatú zátvorku, ale iba, ak už
tento prvok existuje. To môže byť mätúce, ak prichádzate z iného jazyka.
Prvky najskôr pridáme metódou append()
, ktoré môžeme v našom
prípade odovzdať číslo (Int
, ktorý sa uloží na koniec poľa)
alebo pokojne ďalšie polia rovnakého typu (teda typu Int
v
našom prípade).
var pole = [Int]() pole.append(34)
Plniť poľa takto 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:
var pole = [Int]() for i in 1...10 { pole.append(i) }
Aby sme pole vypísali, môžeme za predchádzajúci kód pripísať:
{SWIFT}
var pole = [Int]()
for i in 1...10 {
pole.append(i)
}
for cislo in pole {
print(cislo, terminator:" ")
}
{/SWIFT}
Teraz už je lepšie vidieť sila iného zápisu for
cyklu vo
Swiftu. Ostatné jazyky mávajú ďalšie foreach, nám ale stačí za
in
miesto definované rady čísel vložiť polia a cyklus prejde
všetky prvky, ku ktorým sa v jeho tele môžeme dostať.
1 2 3 4 5 6 7 8 9 10
Pole má vlastnosť count
, kde je uložený počet prvkov.
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 hranatých zátvoriek a prvky oddeľujeme čiarkou:
let simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
Pretože nechceme, aby nám niekto obsah poľa menil, deklarujeme ho pomocou
let
a tým sa pole stáva konštantná. Vynechali sme upresnenie
typu, pretože Swift ľahko spozná, že ide o pole stringov. Samozrejme nám
ale nič nebráni ho doplniť:
let simpsonovi : [String] = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
Pole často slúži na ukladanie medzivýsledkov, ktoré sa potom ďalej v programe používajú. Keď potrebujeme nejaký výsledok 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 dostupné pre pole
Swift nám poskytuje pomocné metódy pre prácu s poľami. Poďme sa na ne pozrieť:
sort()
a sorted()
Ako už názov napovedá, metódy nám poľa zoradí. Metóda
sort()
zotriedi existujúce pole (takže musí byť deklarované s
var
) a sorted(
) nám vráti nové zotriedené poľa,
takže ho nesmiete zabudnúť priradiť do premennej. Metódy sú dokonca tak
šikovné, že pracujú podľa toho, čo máme v poli uložené. Hodnoty typu
String
sa triedia podľa abecedy, čísla podľa veľkosti. Skúsme
si zotrieďiť a vypísať našu rodinku Simpson:
{SWIFT}
var simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpsonovi.sort()
for simpson in simpsonovi {
print(simpson)
}
{/SWIFT}
výstup:
Bart Homer Lisa Maggie Marge
A spôsob zoradenie pomocou metódy sorted()
:
{SWIFT}
var simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
let simpsonovi_sorted = simpsonovi.sorted()
for simpson in simpsonovi_sorted {
print(simpson)
}
{/SWIFT}
výstup:
Bart Homer Lisa Maggie Marge
Skúste si urobiť polia čísel a vyskúšajte si, že to naozaj funguje aj pre nich.
reverse()
a
reversed()
Tieto metódy nám poľa otočia (prvý prvok bude ako posledná atď.).
Princíp je opäť rovnaký ako u triedenie. Metóda reverse()
zotriedi existujúce pole, reversed()
nám potom zoradené pole
vráti. Toho môžeme využiť napr. Pre triedenie pospiatky:
{SWIFT}
var simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpsonovi.sort()
simpsonovi.reverse()
for simpson in simpsonovi {
print(simpson)
}
{/SWIFT}
výstup:
Marge Maggie Lisa Homer Bart
index(of: )
Vracia index daného prvku. Metóda nám vráti Optional(Int)
,
pretože sa môže stať, že prvok v poli jednoducho neexistuje a v takom
prípade nemá zmysel vracať akúkoľvek hodnotu. Optionals by ste mali poznať
z predchádzajúcej lekcie. Aby sme sa k možnej hodnote dostali bezpečne,
použijeme konštrukciu if let
, ktorá do premennej pozície
priradí hodnotu indexu Simpsni, ak taký v našom poli existuje. Ak neexistuje,
tak sa vykoná else
vetva.
{SWIFT}
let simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
print("Ahoj zadaj svojho obľúbeného Simpsni (z rodiny Simpson): ");
let simpson = readLine()!
if let pozice = simpsonovi.index(of: simpson) {
print("Jo, to je môj \(pozice + 1). najobľúbenejšie Simpson!")
} else {
print("Hele, toto nie je Simpson!")
}
{/SWIFT}
výstup:
Ahoj zadaj svojho obľúbeného Simpsni (z rodiny Simpsů): Homer Jo, to je môj 1. najobľúbenejšie Simpson!
Kopírovanie pole
Občas sa môže stať, že z nejakého dôvodu potrebujete presnú kópiu
vášho poľa. To je vo Swiftu buď veľmi jednoduché a alebo pomerne
zdĺhavé. Záleží totiž na tom, či sa vaše pole skladá z hodnotových
typov (Int
, Double
, String
) alebo
referenčných (inštancie tried, o tých sa podrobne zabavíme až v ďalších
Swift kurzoch). V prvom prípade stačí vytvoriť novú premennú polia a to
existujúce doň priradiť. Použijeme naše pole Simpsonovcov, ktoré sa
skladá z hodnôt typu String
- teda hodnotových typov a
vytvoríme jeho kópiu.
var simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"] var kopieSimpsnu = simpsonovi
Prípad s referenčnými dátovými typmi zatiaľ nebudeme riešiť.
count
count
sme si už spomenuli, obsahuje dĺžku poľa. Nie je
metódou, ale vlastností, nepíšu sa za ňu teda zátvorky
()
.
isEmpty
Ako asi tušíte, táto vlastnosť vráti true
, ak je naša pole
prázdne. Je to lepšie, než sa pýtať, či je počet (count
)
rovný nule az kódu je hneď jasné, že nás zaujíma možná prázdnosť
poľa.
min()
a max()
Matematické metódy, vracajúci najmenší prvok (min()
),
najväčší prvok (max()
). Výsledok vráti ako
Optional
, pre prípad, že by pole bolo prázdne.
first
a last
Už podľa názvu vlastnosti vráti prvý a posledný prvok.
contains()
Metóda vracia true
/ false
podľa toho, či sa
prvok, uvedený v parametri metódy, v danom poli nachádzajú.
Mazanie prvkov
Moderné prevedenie poľa vo Swiftu nám umožňuje pohodlne mazať prvky.
remove(at: )
Metóda remove()
odstráni z poľa prvok na nami zadanom indexe.
Musíme si ale dať pozor, aby index skutočne existoval, inak kód skončí
chybou. Častejšie asi budete chcieť z poľa zmazať konkrétny prvok miesto
prvku na vybranom indexe. Swift bohužiaľ neponúka jednoduchú metódu, ktorá
toto zabezpečí, môžeme si ale pomôcť metódou index(of: )
,
ktorú už poznáme:
if let bartIndex = simpsonovi.index(of: "Bart") { simpsonovi.remove(at: bartIndex) }
Takto môžeme z nášho poľa Simpson zmazať Barta. Myslite na to, že pole
musí byť deklarované ako var
, pretože konštantné cez
let
nám nedovolí úpravy. Metóda remove(at: )
zmazaný prvok zároveň vráti, ak by ste s ním chceli pracovať.
removeAll()
Tu nie je veľmi čo vysvetľovať. Metóda jednoducho z poľa odstráni
všetky prvky. Dostupná je ešte variant s parametrom
keepingCapacity
. Pole si totiž na pozadí drží kapacitu pre
prvky a v prípade potreby sa zväčšuje. Ak máte v poli mnoho prvkov, chcete
ich odstrániť, ale viete, že ho čoskoro naplníte ďalšími v podobnom
počte, môžete Swiftu ušetriť prácu s opätovným budovaním kapacity. Nie
je to ale nič dôležité a pokojne používajte removeAll()
bez
parametra.
removeLast()
a
popLast()
Obe metódy odstráni posledný prvok v poli a vráti nám ho. Ako sa teda
líši? Zásadne v prípade, že je pole prázdne. removeLast()
v
takom prípade vyvolá chybu, zatiaľ čo popLast()
jednoducho
vráti prázdny Optional
. Ak viete, že pole určite nebude
prázdne, bude jednoduchšie využiť removeLast()
, pretože
nemusíte riešiť rozbaľovaní Optional
.
Tieto metódy sa hodí aj v prípade, že chcete pomocou poľa emulovať
dátovú štruktúru zásobník (Stack), ktorú Swift oproti ďalším jazykom
neponúka. Jej princíp je prostý. Funguje ako pomyselný štós papierov na
stole. Nové prvky (papiere) vždy prídu navrch a pri odoberaní sa najskôr
dostaneme k tým vrchným - teda tým, ktoré boli pridané posledne. Pomocou
append()
metódy, ktorá pridáva na koniec poľa a týchto
removeLast()/popLast()
, jednoducho docielite rovnakého
správania.
To by pre dnešok stačilo, môžete si s poľom hrať. V budúcej lekcii, Riešené úlohy k 7. lekcii Swift , na vás čaká prekvapenie
V nasledujúcom cvičení, Riešené úlohy k 7. lekcii Swift, 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é 21x (104.8 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Swift