Lekce 11 - Pole v JavaScriptu podruhé - Řazení prvků a 2D pole
V minulé lekci, Pole v JavaScriptu, jsme se naučili používat pole. Ukázali jsme si práci s prvky pole.
V tutoriálu základů JavaScriptu se budeme věnovat další práci s polem. Ukážeme si, jak prvky pole seřadit. Představíme si také pole polí, tedy dvojrozměrné pole. Využijeme jej při tvorbě aplikace, která bude mít za úkol zjistit, kdo má daný den v roce svátek.
Řazení prvků v poli
Položky v poli lze jednoduše seřadit
metodou sort()
.
Řazení textu
Pokud jsou v poli textové řetězce, metoda sort()
nám je
seřadí podle abecedy (vzestupně):
let jmena = ["Dan", "Bohouš", "Cyril", "Anna"]; jmena.sort(); for (let jmeno of jmena) { document.body.innerHTML += jmeno + " "; }
Kód výše vytvoří pole se 4 textovými řetězci. Následně jeho
položky seřadí podle abecedy. Nakonec všechny prvky pole vypíše cyklem
for
.
Výstup v prohlížeči:
Vidíme, že se jména v poli seřadila podle abecedy.
Obrácené pořadí a sestupné řazení
Pořadí prvků v poli můžeme otočit
pomocí metody reverse()
. Tak bude první prvek jako poslední,
druhý jako předposlední atd. Přidejme otočení prvků pole do našeho
příkladu. Jelikož máme pole seřazené, bude výsledkem otočení pole
seřazené od Z do A, tedy sestupně. Do předchozího příkladu tedy přidáme
volání této metody před cyklus pro výpis prvků pole:
let jmena = ["Dan", "Bohouš", "Cyril", "Anna"]; jmena.sort(); jmena.reverse(); // Přidaný řádek for (let jmeno of jmena) { document.body.innerHTML += jmeno + " "; }
Výstup v prohlížeči:
Řazení čísel
Pokud máme v poli čísla, asi byste čekali, že je metoda
sort()
seřadí od nejnižšího po nejvyšší. To se ale
nestane.
Pozor! JavaScript prvky pole řadí vždy jako
texty, i když jsou to čísla! To znamená, že 11
je
dříve než 2
, protože znak "1"
je před znakem
"2"
.
Vyzkoušejme si to:
let cisla = [5, 3, 30, 25]; cisla.sort(); for (let cislo of cisla) { document.body.innerHTML += cislo + " "; }
Výstup:
Vidíme, že metoda sort()
čísla opravdu neseřadí jako
čísla.
Parametr metody sort()
Abychom docílili správného výsledku, musíme metodě sort()
předat parametr, jak má prvky pole porovnávat. Parametrem předáme
funkci, ve které od sebe vždy dva porovnávané prvky pole
odečteme. Tím vznikne buď kladný nebo záporný výsledek (podle toho, zda
je číslo větší nebo menší než to druhé) a na jeho základě si už
sort()
prvek správně zařadí:
let cisla = [5, 3, 30, 25]; cisla.sort(function(a, b) { return a - b }); for (let cislo of cisla) { document.body.innerHTML += cislo + " "; }
V prohlížeči si můžeme ověřit, že jsou čísla již seřazena správně jako čísla:
Pokud vás funkce zmátla, vůbec to nevadí. Budeme se jim podrobně věnovat v lekci Funkce v JavaScriptu se spoustou dalších příkladů a zde je zmíněná jen proto, aby byly informace o poli hezky u sebe. Zápis funkcí a vše o nich si tedy ještě podrobně ukážeme.
Dvourozměrné pole v JavaScriptu
Mnohé z nás asi nepřekvapí, že JavaScript umožňuje vytvořit také pole, které obsahuje další pole jako své prvky. Hovoříme pak o poli polí nebo o dvojrozměrném poli.
Dvourozměrné pole si můžeme v paměti představit jako tabulku a mohli bychom takto reprezentovat např. rozehranou partii piškvorek. Pokud bychom se chtěli držet reálných aplikací, můžeme si představit, že do 2D pole budeme ukládat informace o obsazenostech sedadel v kinosálu. Situaci bychom si mohli graficky znázornit např. takto:

(Na obrázku je vidět 2D pole reprezentující obsazenost kinosálu)
Kinosál by byl v praxi samozřejmě větší, ale jako ukázka nám toto
pole postačí. 0
znamená volno, 1
obsazeno. Později
bychom mohli doplnit i 2
pro rezervováno a podobně.
Vícerozměrná pole využijeme zejména, pokud programujeme nějakou simulaci, například hru.
Deklarace 2D pole
Dvojrozměrné pole je možné deklarovat a naplnit daty takto:
let kinosal = [ [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 1, 1, 1, 0], [1, 1, 1, 1, 1] ];
Proměnná kinosal
je pole, které obsahuje jako své prvky
několik dalších polí, představující jednotlivé řádky výsledného 2D
pole.
Přístup k prvkům 2D pole
Pokud bychom nyní chtěli např. nastavit prvek úplně vlevo nahoře na
hodnotu 1
, musíme uvést dvě hranaté závorky a v nich
index řádku a index sloupce. První řádek
i sloupec mají indexy 0
:
kinosal[0][0] = 1;
Tento řádek nemusíme zanášet do výsledného programu.
Vytvoření 2D pole programově
Když by bylo 2D pole větší nebo jsme předem nevěděli jeho velikost, je výhodnější jej vytvořit programově pomocí cyklů.
Vytvoření prázdného 2D pole pomocí cyklů
Prvně si vytvoříme prázdné pole:
let kinosal = [];
Následně na jeho indexech vytvoříme několik nových polí, pro každý řádek jedno:
for (let i = 0; i < 5; i++) { kinosal[i] = []; // Přidání řádku }
Zbývá jen vnitřní pole, která představují řádky, naplnit nulami. To uděláme dalším vnořeným cyklem. Celý kód pak vypadá takto:
let kinosal = []; for (let i = 0; i < 5; i++) { kinosal[i] = []; // Přidání řádku for (let j = 0; j < 5; j++) { kinosal[i][j] = 0; // Naplnění řádku nulami } }
První cyklus udává index řádku, druhý vnořený cyklus udává index prvku v řádku (samozřejmě si cykly můžeme i otočit a souřadnice by potom byly prohozené, např. u grafických aplikací je zvykem prvně zadávat index sloupce a až potom řádku).
Naplnění 2D pole daty
Nyní kinosál naplníme jedničkami tak, jak je vidět na obrázku:

Pro přístup k prvku 2D pole musíme zadat dvě souřadnice pomocí indexů.
Prostřední prvek našeho kinosálu je tedy na pozici
kinosal[2][2]
. Za předešlý kód přidáme:
kinosal[2][2] = 1; // Prostřední jednička // Úprava 4. řádku for (let i = 1; i < 4; i++) { kinosal[3][i] = 1; } // Naplnění celého posledního řádku for (let i = 0; i < 5; i++) { kinosal[4][i] = 1; }
Výpis 2D pole
Výpis pole do stránky provedeme pomocí cyklu. Budeme potřebovat dva cykly (jeden nám proiteruje řádky a druhý sloupce). Je to stejný princip, jako když jsme vypisovali dvěma vnořenými cykly malou násobilku. Jako správní programátoři nevložíme počet řádků a sloupců do cyklů napevno, jelikož se může změnit.
Musíme však pamatovat na skutečnost, že když se zeptáme na
kinosal.length
, bude obsahovat počet vnořených polí (řádků).
Abychom získali počet sloupců (délku vnitřního pole), zeptáme se na
kinosal[i].length
.
Cykly zanoříme do sebe tak, aby nám vnější cyklus projížděl řádky a vnitřní sloupce v aktuálním řádku. Pro výpis využijeme HTML tabulku. Oba cykly musí mít samozřejmě jinou řídící proměnnou. Doplníme tedy tento kód:
let tabulka = "<table border='1'>"; for (let i = 0; i < kinosal.length; i++) { tabulka += "<tr>"; for (let j = 0; j < kinosal[i].length; j++) { tabulka += "<td>" + kinosal[i][j] + "</td>"; } tabulka += "</tr>"; } tabulka += "</table>"; document.body.innerHTML += tabulka;
Když nyní spustíme celý příklad v prohlížeči, dostaneme tento výstup:
Příklad – Výpis svátků pro daný den
Na závěr si vytvoříme skript vypisující, kdo má dnes svátek. Veřte nebo ne, použijeme k tomu právě 2D pole. To bude mít 12 řádků jako měsíců a v každém řádku budou za sebou uložena jména svátků v daném měsíci.
Příprava dat
Nejprve si vytvoříme prázdné vnější pole řádků (měsíců). Každý
měsíc pak přidáme metodou push()
jako pole již naplněné
jmény. Postupně takto doplníme položky se všemi jmény v roce:
// Tento skript pochází z webu itnetwork.cz // Smí být libovolně používán i modifikován, ale nesmí z něj být umazán tento text // vytvoříme si prázdné pole měsíců a postupně do něj přidáme pole se svátky v daném měsíci let mesice = []; // leden mesice.push(["Nový rok, Den obnovy samostatného českého státu", "Karina", "Radmila", "Diana", "Dalimil", "Tři králové", "Vilma", "Čestmír", "Vladan", "Břetislav", "Bohdana", "Pravoslav", "Edita", "Radovan", "Alice", "Ctirad", "Drahoslav", "Vladislav", "Doubravka", "Ilona", "Běla", "Slavomír", "Zdeněk", "Milena", "Miloš", "Zora", "Ingrid", "Otýlie", "Zdislava", "Robin", "Marika"]); // únor mesice.push(["Hynek", "Nela", "Blažej", "Jarmila", "Dobromila", "Vanda", "Veronika", "Milada", "Apolena", "Mojmír", "Božena", "Slavěna", "Věnceslav", "Valentýn", "Jiřina", "Ljuba", "Miloslava", "Gizela", "Patrik", "Oldřich", "Lenka", "Petr", "Svatopluk", "Matěj", "Liliana", "Dorota", "Alexandr", "Lumír", "Horymír"]); // březen mesice.push(["Bedřich", "Anežka", "Kamil", "Stela", "Kazimír", "Miroslav", "Tomáš", "Gabriela", "Františka", "Viktorie", "Anděla", "Řehoř", "Růžena", "Rút, Matylda", "Ida", "Elena, Herbert", "Vlastimil", "Eduard", "Josef", "Světlana", "Radek", "Leona", "Ivona", "Gabriel", "Marián", "Emanuel", "Dita", "Soňa", "Taťána", "Arnošt", "Kvido"]); // duben mesice.push(["Hugo", "Erika", "Richard", "Ivana", "Miroslava", "Vendula", "Heřman, Hermína", "Ema", "Dušan", "Darja", "Izabela", "Julius", "Aleš", "Vincenc", "Anastázie", "Irena", "Rudolf", "Valérie", "Rostislav", "Marcela", "Alexandra", "Evženie", "Vojtěch", "Jiří", "Marek", "Oto", "Jaroslav", "Vlastislav", "Robert", "Blahoslav"]); // květen mesice.push(["Svátek práce", "Zikmund", "Alexej", "Květoslav", "Klaudie", "Radoslav", "Stanislav", "Den vítězství", "Ctibor", "Blažena", "Svatava", "Pankrác", "Servác", "Bonifác", "Žofie", "Přemysl", "Aneta", "Nataša", "Ivo", "Zbyšek", "Monika", "Emil", "Vladimír", "Jana", "Viola", "Filip", "Valdemar", "Vilém", "Maxmilián", "Ferdinand", "Kamila"]); // červen mesice.push(["Laura", "Jarmil", "Tamara", "Dalibor", "Dobroslav", "Norbert", "Iveta, Slavoj", "Medard", "Stanislava", "Gita", "Bruno", "Antonie", "Antonín", "Roland", "Vít", "Zbyněk", "Adolf", "Milan", "Leoš", "Květa", "Alois", "Pavla", "Zdeňka", "Jan", "Ivan", "Adriana", "Ladislav", "Lubomír", "Petr a Pavel", "Šárka"]); // červenec mesice.push(["Jaroslava", "Patricie", "Radomír", "Prokop", "Cyril, Metoděj", "Den upálení mistra Jana Husa", "Bohuslava", "Nora", "Drahoslava", "Libuše, Amálie", "Olga", "Bořek", "Markéta", "Karolína", "Jindřich", "Luboš", "Martina", "Drahomíra", "Čeněk", "Ilja", "Vítězslav", "Magdaléna", "Libor", "Kristýna", "Jakub", "Anna", "Věroslav", "Viktor", "Marta", "Bořivoj", "Ignác"]); // srpen mesice.push(["Oskar", "Gustav", "Miluše", "Dominik", "Kristián", "Oldřiška", "Lada", "Soběslav", "Roman", "Vavřinec", "Zuzana", "Klára", "Alena", "Alan", "Hana", "Jáchym", "Petra", "Helena", "Ludvík", "Bernard", "Johana", "Bohuslav", "Sandra", "Bartoloměj", "Radim", "Luděk", "Otakar", "Augustýn", "Evelína", "Vladěna", "Pavlína"]); // září mesice.push(["Linda, Samuel", "Adéla", "Bronislav", "Jindřiška", "Boris", "Boleslav", "Regína", "Mariana", "Daniela", "Irma", "Denisa", "Marie", "Lubor", "Radka", "Jolana", "Ludmila", "Naděžda", "Kryštof", "Zita", "Oleg", "Matouš", "Darina", "Berta", "Jaromír", "Zlata", "Andrea", "Jonáš", "Václav, Den české státnosti", "Michal", "Jeroným"]); // říjen mesice.push(["Igor", "Olivie, Oliver", "Bohumil", "František", "Eliška", "Hanuš", "Justýna", "Věra", "Štefan, Sára", "Marina", "Andrej", "Marcel", "Renáta", "Agáta", "Tereza", "Havel", "Hedvika", "Lukáš", "Michaela", "Vendelín", "Brigita", "Sabina", "Teodor", "Nina", "Beáta", "Erik", "Šarlota, Zoe", "Den vzniku samostatného československého státu", "Silvie", "Tadeáš", "Štěpánka"]); // listopad mesice.push(["Felix", "Památka zesnulých (dušičky)", "Hubert", "Karel", "Miriam", "Liběna", "Saskie", "Bohumír", "Bohdan", "Evžen", "Martin", "Benedikt", "Tibor", "Sáva", "Leopold", "Otmar", "Mahulena, Den boje za svobodu a demokracii", "Romana", "Alžběta", "Nikola", "Albert", "Cecílie", "Klement", "Emílie", "Kateřina", "Artur", "Xenie", "René", "Zina", "Ondřej"]); // prosinec mesice.push(["Iva", "Blanka", "Svatoslav", "Barbora", "Jitka", "Mikuláš", "Benjamín", "Květoslava", "Vratislav", "Julie", "Dana", "Simona", "Lucie", "Lýdie", "Radana", "Albína", "Daniel", "Miloslav", "Ester", "Dagmar", "Natálie", "Šimon", "Vlasta", "Adam, Eva, Štědrý den", "1. svátek vánoční", "Štěpán, 2. svátek vánoční", "Žaneta", "Bohumila", "Judita", "David", "Silvestr"]);
Zjištění svátku
To nejtěžší máme za sebou! Nyní stačí zjistit jen:
- Aktuální den pomocí metody
getDate()
. Metoda vrací hodnotu1
až31
, pokud tedy chceme získat odpovídající index v poli pro aktuální den, musíme odečíst1
, protože indexy pole jsou od nuly. - Aktuální měsíc metodou
getMonth()
. Ta vrací hodnotu od0
do11
, kde0
odpovídá lednu a11
prosinci, získanou hodnotu tedy již nemusíme upravovat.
Nakonec vybereme hledaný prvek v poli polí, použijeme tedy nejprve index měsíce a poté index dne:
// nyní přistoupíme k samotnému výpisu let dnes = new Date(); let den = dnes.getDate()-1; let mesic = dnes.getMonth(); document.body.innerHTML += "Dnes má svátek " + mesice[mesic][den];
Výsledek:
Gratuluji, nyní máte kromě ukázky použití pole i užitečný skript na svůj web 🏆
V následujícím cvičení, Řešené úlohy k 10.-11. lekci JavaScriptu, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 309x (4.47 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript