Práce s tabulky

Pokud zvládnete tabulky, pak jste na dobré cestě zvládnout celý jazyk. Jedna z posledních základních věcí co zbývá vysvětlit jsou právě tabulky. Nechal jsem si je na konec, protože v nich uplatníme téměř vše co jsme se naučili. K ovládání tabulek nám slouží také třída table.

Základní logika tabulek

Tabulka je nehomogenní struktura dat. Znamená to, že data v ní nejsou stejného datového typu. Můžeme tak mít na stejné úrovni. K jednotlivým úrovním tabulky přistupujeme přes tzv. indexy. Index může být zapsán jako text za tečnou u názvu tabulky, a nebo jako číslo v hranatých ([]) závorkách. Lua indexuje položky od jedničky - to znamená, že pokud bude tabulka automaticky vygenerována, její první index bude 1. Tabulku deklarujeme (uvedeme) tak, že do ní přiřadíme hodnotu {}.

Příklad:

1local tabulka = {};
2-- ukazka txt indexu - chovaji se jako obyc.
3-- promenne jen jsou v tabulce
4tabulka.index1 = 5;
5tabulka.index2 = 1.86464;
6tabulka.index3 = "Ahoj";
7-- ukazka ciselneho indexu
8tabulka[1] = "Ahoj";
9tabulka[2] = 64;
10-- vytvoreni tabulky v tabulce
11tabulka[3] = {};
12tabulka[3].index1 = 6;
13
14-- vypsani hodnot
15for _,v in pairs(tabulka) do
16 print(v);
17end;
18--[[
19 LOG:
20 "Ahoj
21 64.000000
22 5.000000
23 Ahoj
24 1.864640
25 "
26]]--

Z příkladu lze vidět, jak se zapisují textové indexy. Vidíme zde také příklad procházení pole pomocí ipairs. V logu budeme mít jeden řádek prázdný - nemůžeme vytisknou pole a tak se vytiskne nic.

Objekty

Objekty jsem zařadil pod tabulky proto, protože se v tabulkách vytvářejí. Objekt není nic jiného než soubor funkcí v tabulce. Jeden velký obejkt používáme neustále - náš skript. Objekt může obsahovat funkce, proměnné atd...

Ukázka jednoduché třídy přes tabulku:

1
2-- Objekt skriptu - vytvoreni tabulky pro objekt
3-- Hra pri inicializaci doplni zbytek
4-- u nasich trid si to musime udelat sami
5mujSkript = {};
6
7function mujSkript.prerequisitesPresent(specializations)
8 return true;
9end;
10
11function mujSkript:load(xmlFile)
12 local promenna = MyClass.new(5);
13 print(promenna:get_value());
14 -- "5"
15end;
16
17function mujSkript:mouseEvent(posX, posY, isDown, isUp, button)
18end;
19
20function mujSkript:keyEvent(unicode, sym, modifier, idDown)
21end;
22
23function mujSkript:update(dt)
24end;
25
26function mujSkript:updateTick(dt)
27end;
28
29function mujSkript:draw()
30end;
31
32-- Objekt muj vytvoreny
33-- K podrobnejsimu rozpisu objektu se dostaneme pozdeji
34MyClass = {};
35MyClass.__index = MyClass;
36
37function MyClass.new(init)
38 local self = setmetatable({}, MyClass);
39 self.value = init;
40 return self;
41end;
42
43function MyClass.set_value(self, newval)
44 self.value = newval;
45end;
46
47function MyClass.get_value(self)
48 return self.value;
49end;
50

K podrobnějšímu rozpisu objektů se dostaneme o hodně později - ale dostaneme se k nim. Toto byla ukázka jednoduchého objektu.

Vícesložková tabulka

Pro někoho je to velká obtíž, ale vědu v tom nehledejte. Je to jen pole v poli. Můžeme mít třeba sedmisložkové pole. Sami poznáte, že je budete velmi využívat. Jako příklad uvedu seznam položek v obchodě, který si vypíšeme:

1local obchod = {};
2obchod.info = {};
3obchod.info.ulice = "Kratochvilova";
4obchod.info.cp = "7/1490";
5obchod.info.mesto = "Ostrava - Moravska Ostrava";
6obchod.info.kraj = "Moravskoslezsky";
7obchod.info.zeme = "CR";
8obchod.nabidka = {};
9obchod.nabidka[1] = {};
10obchod.nabidka[1].cena = 5000;
11obchod.nabidka[1].nazev = "Bonbony";
12obchod.nabidka[1].dostupnost = "Ihned";
13obchod.nabidka[2] = {};
14obchod.nabidka[2].cena = 1000;
15obchod.nabidka[2].nazev = "Ubytovani";
16obchod.nabidka[2].dostupnost = "Ihned";
17obchod.nabidka[3] = {};
18obchod.nabidka[3].cena = 500;
19obchod.nabidka[3].nazev = "Voda";
20obchod.nabidka[3].dostupnost = "5 dní";
21print("Adresa obchodu:");
22print(obchod.info.ulice.." "..obchod.info.cp);
23print(obchod.info.mesto);
24print("");
25print("Nabidka obchodu:");
26for _,v in pairs(obchod.nabidka) do
27 print(v.nazev.." - Cena: "..v.cena.." Kc");
28 print("Dostupnost: "..v.dostupnost);
29 print("");
30end;
31
32--[[ LOG:
33 Adresa obchodu:
34 Kratochvilova 7/1490
35 Ostrava - Moravska Ostrava
36
37 Nabidka obchodu:
38 Bonbony - Cena: 5000 Kc
39 Dostupnost: Ihned
40
41 Ubytovani - Cena: 1000 Kc
42 Dostupnost: Ihned
43
44 Voda - Cena: 500 Kc
45 Dostupnost: 5 dní
46]]--
47

Vícesložkovou tabulku vytvoříme tak, že položce pole přidělíme hodnotu {}

Knihovna table

Tak jako řetězce mají knihovnu string, má Lua knihovnu také pro tabulky. Tato knihovna obsahuje funkce pro práci s tabulkami a my si je dnes popíšeme. Tato knihovna je o něco menší než ty předchozí, protože téměř cokoli co chceme udělat s tabulkou si můžeme udělat jinak než přes tuto knihovnu.

table.concat();

Tato funkce slouží ke spojení obsahu tabulky v jeden řetězec. Jení vstupní parametry jsou tabulka a nepovinný oddělovač, začátek a konec. Funkce spojí obsah tabulky a pokud je přítomen oddělovač, vloží ho mezi jednotlivé položky. Výstupním parametrem je řetězec, který vznikne při spojení. Pokud není přítomen konec ale jen začátek, spojí se to co je za začátkem (včetně).

Pozor! Pokud bude tabulka obsahovat funkce nebo další tabulky, funkce selže.

1-- naplneni pole pri inicializaci
2local tabulka = {1,68,"f ",65,"fabr"};
3print(table.concat(tabulka));
4-- "168f 65fabr"
5print(table.concat(tabulka," - "));
6-- "1 - 68 - f - 65 - fabr"
7-- vytvoreni tabulky na radku
8print(table.concat({{},5,84,6,2}));
9-- "Error: Running LUA method 'update'."
10-- "C:/Users/Martin/Documents/My Games/FarmingSimulator2015/mods//JD_pack/Script/MujSkript.lua:16: invalid value (table) at index 1 in table for 'concat'"
11

Zde vidíte dokonce jakou chybu vám hra vygeneruje pokud pro concat zvolíte špatnou tabulku.

table.getn(); , #

Funkce table.getn(); vrací počet záznmů v tabulce. Vstupním parametrem je tabulka, výstupním pak číslo, kolik obsahuje záznamů. Stejnou funkci plní znak # před názvem tabulky. Pozor: table.getn(); se přestává používat - doporučuji používat #. Ukázka:

1-- naplneni pole pri inicializaci
2local tabulka = {1,68,"f ",65,"fabr"};
3print(table.getn(tabulka));
4-- "5"
5print(#tabulka);
6-- "5"

table.sort();

Funkce seřadí tabulku podle hodnot. Parametry jsou tabulka a porovnávací funkce. Výstup není žádný - změny se provedou přímo v tabulce. Porovnávací funkce musí vracet pravdivostní hodnotu true nebo false. Vstupními parametry této porovnávací funkce jsou hodnoty a a b. Vrácená hodnota porovnávací funkce určuje, zda má být parametr a umístěn před parametrem b.

Ukázka table.sort();:

1-- naplneni pole pri inicializaci
2local tabulka = {1,68,5,65,456};
3-- serazeni bez porovnavaci funkce:
4table.sort(tabulka);
5print(table.concat(tabulka," - "));
6-- "1 - 5 - 65 - 68 - 456"
7
8-- pouziti porovnavaci funkce:
9table.sort(tabulka,function(a,b)
10 -- B bude pred A pokud je mensi
11 return (a>b);
12end);
13print(table.concat(tabulka," - "));
14-- "456 - 68 - 65 - 5 - 1"
15
16tabulka = {"afn", 64, "b", 69,2};
17table.sort(tabulka);
18print(table.concat(tabulka," - "));
19-- "Error: Running LUA method 'update'."
20-- "attempt to compare number with string"
21
22-- Tuto chybu opravime tak, ze pouzijeme vlastni porovnavaci funkci.
23table.sort(tabulka, function(a,b)
24 if type(a) == "string" and type(b) == "number" then
25 return false;
26 elseif type(b) == "string" and type(a) == "number" then
27 return true;
28 elseif type(b) == "string" and type(a) == "string" then
29 return a
30 end;
31end);
32-- diky teto funkci si posuneme vsechny texty na konec tabulky
33print(table.concat(tabulka," - "));
34-- "2 - 64 - 69 - afn - b"
35

V přikladu je použita funkce type o které si budeme povídat později. Tato funkce vrací datový typ dané proměnné.

table.insert();

Tato funkce má za úkol vkládat do tabulky data. Vstupními parametry jsou tabulka, nepovinná pozice a povinná hodnota. Funkce nevrací nic - změny se provedou přímo v tabulce. Pokud není určena pozice prvku, bude vložen na konec tabulky. Při určení pozice jsou následující prvky v tabulce posunuty. Ukázka:

1local tabulka = {"a",77,45,"asdfg"};
2print(table.concat(tabulka,", "));
3-- "a, 77, 45, asdfg"
4table.insert(tabulka,"vlozeny jsem");
5print(table.concat(tabulka,", "));
6-- "a, 77, 45, asdfg, vlozeny jsem"
7table.insert(tabulka,3,"hihi");
8print(table.concat(tabulka,", "));
9-- "a, 77, hihi, 45, asdfg, vlozeny jsem"

table.remove();

Funkce odstraní jeden záznam z tabulky podle zadaných parametrů. Těmi jsou tabulka a nepovinná pozice prvku. Pokud není udána pozice prvku, smaže se poslední záznam - jinak se maže záznam na dané pozici. Ukázka:

1local tabulka = {"a",77,45,"asdfg"};
2table.insert(tabulka,"vlozeny jsem");
3table.insert(tabulka,3,"hihi");
4table.remove(tabulka);
5print(table.concat(tabulka,", "));
6-- "a, 77, hihi, 45, asdfg"
7table.remove(tabulka, 2);
8print(table.concat(tabulka,", "));
9-- "a, hihi, 45, asdfg"

Související video

Soubory ke stažení

  1. mujskript.lua