IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

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.

Štruktúra poľa vo Swift - Základné konštrukcie jazyka Swift

(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ť:

for cislo in pole {
    print(cislo, terminator:" ")
}

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:

var simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpsonovi.sort()
for simpson in simpsonovi {
    print(simpson)
}

výstup:

Bart
Homer
Lisa
Maggie
Marge

A spôsob zoradenie pomocou metódy sorted():

var simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]

let simpsonovi_sorted = simpsonovi.sorted()
for simpson in simpsonovi_sorted {
    print(simpson)
}

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:

var simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpsonovi.sort()
simpsonovi.reverse()
for simpson in simpsonovi {
    print(simpson)
}

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.

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!")
}

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

 

Predchádzajúci článok
Typový systém: Optionals vo Swift
Všetky články v sekcii
Základné konštrukcie jazyka Swift
Preskočiť článok
(neodporúčame)
Riešené úlohy k 7. lekcii Swift
Článok pre vás napísal Filip Němeček
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje vývoji iOS aplikací (občas macOS)
Aktivity