Letní akce! Lákají tě IT školení C#, Javy a PHP v Brně? Přihlas se a napiš nám do zpráv kód "BRNO 500" pro slevu 500 Kč na libovolný brněnský kurz. Lze kombinovat se slevami uvedenými u školení i použít pro více kurzů. Akce končí 28.7.

Lekce 7 - Pole ve Swift

Swift Základní konstrukce Pole ve Swift

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci kurzu, Typový systém: Optionals ve Swift, jsme se naučili používat Optionals. Dnes si ve Swift tutoriálu 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 50 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, takhle 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 ve Swift

(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). Swift k polím přistupuje poměrně moderně. Neřeší velikost (ani ji nemůžete pevně zadat) a pro přidávání prvků se používá metoda, takže nemusíte řešit indexy. Tomuto typu kolekce (kontejnerové struktury) se v některých jazycích říká spíše seznam, než pole. Swift jej ovšem jako pole označuje. Pro hromadnou manipulaci s prvky pole se používají cykly.

Pole deklarujeme pomocí hranatých závorek a obyčejných závorek:

var pole = [Int]()

Výraz pole je samozřejmě název naší proměnné. Nyní jsme však pouze deklarovali, že v proměnné bude pole Intů. Musíme ho založit, abychom ho mohli používat.

K prvkům pole potom přistupujeme přes hranatou závorku, ale pouze, pokud již tento prvek existuje. To může být matoucí, pokud přicházíte z jiného jazyka. Prvky nejdříve přidáme metodou append(), které můžeme v našem případě předat číslo (Int, který se uloží na konec pole) nebo klidně další pole stejného typu (tedy typu Int v našem případě).

var pole = [Int]()
pole.append(34)

Plnit pole takto 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:

var pole = [Int]()
for i in 1...10 {
        pole.append(i)
}

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

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

Nyní už je lépe vidět síla jiného zápisu for cyklu ve Swiftu. Ostatní jazyky mívají další foreach, nám ale stačí za in místo definované řady čísel vložit pole a cyklus projde všechny prvky, ke kterým se v jeho těle můžeme dostat.

1 2 3 4 5 6 7 8 9 10

Pole má vlastnost count, kde je uložen počet prvků.

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 hranatých závorek a prvky oddělujeme čárkou:

let simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Meggie"]

Protože nechceme, aby nám někdo obsah pole měnil, deklarujeme ho pomocí let a tím se pole stává konstantní. Vynechali jsme upřesnění typu, protože Swift snadno pozná, že jde o pole stringů. Samozřejmě nám ale nic nebrání ho doplnit:

let simpsonovi : [String] = ["Homer", "Marge", "Bart", "Lisa", "Meggie"]

Pole často slouží k ukládání mezivýsledků, které se potom dále v programu používají. Když potřebujeme nějaký výsledek 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 dostupné pro pole

Swift nám poskytuje pomocné metody pro práci s poli. Pojďme se na ně podívat:

sort() a sorted()

Jak již název napovídá, metody nám pole seřadí. Metoda sort() setřídí existující pole (takže musí být deklarované s var) a sorted() nám vrátí nové setříděné pole, takže ho nesmíte zapomenout přiřadit do proměnné. Metody jsou dokonce tak chytré, že pracují podle toho, co máme v poli uložené. Stringy třídí podle abecedy, čísla podle velikosti. Zkusme si setřídit a vypsat naši rodinku Simpsnů:

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

Bart
Homer
Lisa
Maggie
Marge

A způsob seřazení pomocí metody sorted():

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

let simpsonovi_sorted = simpsonovi.sorted()
for simpson in simpsonovi_sorted {
        print(simpson)
}
Bart
Homer
Lisa
Maggie
Marge

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

reverse() a reversed()

Tyto metody nám pole otočí (první prvek bude jako poslední atd.). Princip je opět stejný jako u třídění. Metoda reverse() setřídí existující pole, reversed() nám potom seřazené pole vrátí. Toho můžeme využít např. pro třídění pozpátku:

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

index(of: )

Metoda nám vrátí Optional(Int), protože se může stát, že prvek v poli prostě neexistuje a v takovém případě nemá smysl vracet jakoukoliv hodnotu. Optionals byste měli znát z předchozí lekce. Abychom se k možné hodnotě dostali bezpečně, použijeme konstrukci if let, která do proměnné pozice přiřadí hodnotu indexu Simpsna, pokud takový v našem poli existuje. Jestliže neexistuje, tak se provede else větev.

let simpsonovi = ["Homer", "Marge", "Bart", "Lisa", "Meggie"]
print("Ahoj, zadej svého oblíbeného Simpsna (z rodiny Simpsů): ");
let simpson = readLine()!
if let pozice = simpsonovi.index(of: simpson) {
        print("Jo, to je můj \(pozice + 1). nejoblíbenější Simpson!")
} else {
        print("Hele, tohle není Simpson!")
}

Ahoj, zadej svého oblíbeného Simpsna (z rodiny Simpsů):
Homer
Jo, to je můj 1. nejoblíbenější Simpson!

Kopírování pole

Občas se může stát, že z nějakého důvodu potřebujete přesnou kopii vašeho pole. To je ve Swiftu buď velmi jednoduché a nebo poměrně zdlouhavé. Záleží totiž na tom, jestli se vaše pole skládá z hodnotových typů (Int, Double, String) nebo referenčních (instance tříd, o těch se podrobně pobavíme až v dalších Swift kurzech). V prvním případě stačí vytvořit novou proměnnou pole a to stávající do něj přiřadit. Použijeme naše pole Simpsonů, které se skládá ze Stringů - tedy hodnotových typů a vytvoříme jeho kopii.

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

var kopieSimpsnu = simpsonovi

Případ s referenčními datovými typy zatím nebudeme řešit.

count

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

isEmpty

Jak asi tušíte, tato vlastnost vrátí true, pokud je naše pole prázdné. Je to lepší, než se ptát, jestli je počet (count) roven nule a z kódu je hned jasné, že nás zajímá možná prázdnost pole.

min() a max()

Matematické metody, vracející nejmenší prvek (min()), největší prvek (max()). Výsledek vrátí jako Optional, pro případ, že by pole bylo prázdné.

first a last

Již podle názvu vlastnosti vrátí první a poslední prvek.

contains()

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

Mazání prvků

Moderní provedení pole ve Swiftu nám umožňuje pohodlně mazat prvky.

remove(at: )

Metoda remove() odstraní z pole prvek na námi zadaném indexu. Musíme si ale dát pozor, aby index skutečně existoval, jinak kód skončí chybou. Častěji asi budete chtít z pole smazat konkrétní prvek místo prvku na vybraném indexu. Swift bohužel nenabízí jednoduchou metodu, která toto zajistí, můžeme si ale pomoci metodou index(of: ), kterou už známe.

if let bartIndex = simpsonovi.index(of: "Bart") {
        simpsonovi.remove(at: bartIndex)
}

Takto můžeme z našeho pole Simpsnů smazat Barta. Myslete na to, že pole musí být deklarováno jako var, protože konstantní přes let nám nedovolí úpravy. Metoda remove(at: ) smazaný prvek zároveň vrátí, pokud byste s ním chtěli pracovat.

removeAll()

Zde není moc co vysvětlovat. Metoda jednoduše z pole odstraní všechny prvky. Dostupná je ještě varianta s parametrem keepingCapacity. Pole si totiž na pozadí drží kapacitu pro prvky a v případě potřeby se zvětšuje. Pokud máte v poli hodně prvků a víte, že jej brzy naplníte dalšími v podobném počtu, můžete Swiftu ušetřit práci s opětovným budováním kapacity. Není to ale nic důležitého a klidně používejte removeAll() bez parametru.

removeLast() a popLast()

Obě metody odstraní poslední prvek v poli a vrátí nám ho. Jak se tedy liší? Zásadně v případě, že je pole prázdné. removeLast() v takovém případě vyvolá chybu, zatímco popLast() jednoduše vrátí prázdný Optional. Pokud víte, že pole určitě nebude prázdné, bude jednoduší využít removeLast(), protože nemusíte řešit rozbalování Optional.

Tyto metody se hodí také v případě, že chcete pomocí pole emulovat datovou strukturu zásobník (Stack), kterou Swift oproti dalším jazykům nenabízí. Její princip je prostý. Funguje jako pomyslný štos papírů na stole. Nové prvky (papíry) vždy přijdou navrch a při odebírání se nejdříve dostaneme k těm vrchním - tedy těm, které byly přidány posledně. Pomocí append() metody, která přidává na konec pole a těchto removeLast()/popLast() jednoduše docílíte stejného chování.

To by pro dnešek stačilo, můžete si s polem hrát. V příští lekci, Textové řetězce ve Swift podruhé - Práce se znaky, na vás čeká překvapení ;-)


 

Stáhnout

Staženo 2x (104.8 kB)
Aplikace je včetně zdrojových kódů v jazyce Swift

 

 

Článek pro vás napsal Filip Němeček
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se příležitostně věnuje vývoji iOS aplikací či těch webových za pomocí frameworku Django. Aktuální projekt: hrejzdarma.cz Twitter: @nemecek_f (neprogramátorské tweety)
Miniatura
Všechny články v sekci
Základní konstrukce jazyka Swift
Miniatura
Následující článek
Cvičení k 7. lekci Swift
Aktivity (6)

 

 

Komentáře

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.

Zatím nikdo nevložil komentář - buď první!