Tabeller i Lua

I denna lektion lär du dig om tabeller i Lua, den enda datastrukturen i språket som kan användas som arrayer, dictionaries, objekt och mer.

Vad är tabeller?

I Lua är tabeller den enda sammansatta datastrukturen. De är flexibla och kraftfulla, och kan användas för att representera:

  • Arrayer (listor med element)
  • Dictionaries (nyckel-värde par)
  • Objektorienterade strukturer
  • Grafer och mycket mer

Tabeller skapas med klammerparenteser {} och är alltid dynamiska. De kan innehålla olika typer av värden i samma tabell.

Använda tabeller som arrayer

När du vill använda tabeller som arrayer (listor), använder du numeriska index som börjar med 1 i Lua (inte 0 som i många andra språk):

-- Skapa en array (lista) med frukter
local frukter = {"äpple", "banan", "apelsin", "päron"}

-- Komma åt enskilda element
print(frukter[1])  -- Skriver ut: äpple (notera: Lua börjar med index 1)
print(frukter[2])  -- Skriver ut: banan

-- Ändra ett element
frukter[3] = "kiwi"
print(frukter[3])  -- Skriver ut: kiwi

-- Lägga till element i slutet
frukter[5] = "ananas"
-- eller använda insert
table.insert(frukter, "mango")  -- Lägger till element i slutet

-- Ta bort element
table.remove(frukter, 2)  -- Ta bort banan (element på index 2)

Längden på en array

Du kan få längden på en array med längdoperatorn #:

local frukter = {"äpple", "banan", "apelsin"}
print("Antal frukter: " .. #frukter)  -- Skriver ut: Antal frukter: 3
Varning! I Lua fungerar längdoperatorn bara pålitligt för "täta" arrayer (arrayer utan nil-värden i mitten).

Tabeller som dictionaries (associativa arrayer)

Tabeller kan också användas som associativa arrayer eller dictionaries, där nycklar kan vara nästan vilket värde som helst (inte bara nummer):

-- Skapa en associativ tabell (dictionary)
local person = {
    namn = "Lisa",
    ålder = 28,
    yrke = "Programmerare",
    ["favorit mat"] = "Pizza"  -- När nyckeln innehåller mellanslag
}

-- Komma åt värden
print(person.namn)           -- Skriver ut: Lisa
print(person["ålder"])       -- Skriver ut: 28 (alternativ syntax)
print(person["favorit mat"]) -- Skriver ut: Pizza (måste använda denna syntax för nycklar med mellanslag)

-- Lägga till nya nyckel-värde par
person.email = "lisa@exempel.se"
person["telefon"] = "070-1234567"

-- Ta bort nyckel-värde par
person.yrke = nil  -- Ta bort yrke

Skillnaden mellan punkt och hakparentes

Det finns två sätt att komma åt värden i en tabell:

  • tabell.nyckel - Enkel syntax för nyckelnamn som följer variabelregler
  • tabell["nyckel"] - Fungerar för alla typer av nycklar, inklusive de med mellanslag eller andra specialtecken

Loopa genom tabeller

Det finns flera sätt att loopa genom tabeller i Lua:

För arrayer (med ipairs)

local frukter = {"äpple", "banan", "apelsin", "päron"}

-- Loopa med ipairs (för arrayer med numeriska index)
for index, värde in ipairs(frukter) do
    print(index .. ": " .. värde)
end

-- Utskrift:
-- 1: äpple
-- 2: banan
-- 3: apelsin
-- 4: päron

För associativa tabeller (med pairs)

local person = {namn = "Lisa", ålder = 28, yrke = "Programmerare"}

-- Loopa med pairs (för alla typer av tabeller)
for nyckel, värde in pairs(person) do
    print(nyckel .. ": " .. värde)
end

-- Utskrift (ordningen kan variera):
-- namn: Lisa
-- ålder: 28
-- yrke: Programmerare
Kom ihåg: Använd ipairs för arrayer och pairs för associativa tabeller. ipairs garanterar ordning men fungerar bara för numeriska index i följd.

Nästlade tabeller

Tabeller kan innehålla andra tabeller, vilket låter dig skapa komplexa datastrukturer:

-- Skapa en nästlad tabell
local elever = {
    {
        namn = "Erik",
        ålder = 16,
        betyg = {matematik = "A", svenska = "B", engelska = "A"}
    },
    {
        namn = "Anna",
        ålder = 17,
        betyg = {matematik = "B", svenska = "A", engelska = "A"}
    }
}

-- Komma åt nästlade värden
print(elever[1].namn)                  -- Skriver ut: Erik
print(elever[2].betyg.svenska)         -- Skriver ut: A
print(elever[1]["betyg"]["matematik"]) -- Skriver ut: A (alternativ syntax)

-- Loopa genom elever och deras betyg
for i, elev in ipairs(elever) do
    print("Elev: " .. elev.namn)
    print("Betyg:")
    
    for ämne, betyg in pairs(elev.betyg) do
        print("  " .. ämne .. ": " .. betyg)
    end
    
    print("") -- Tom rad mellan elever
end

Tabellfunktioner

Lua har flera inbyggda funktioner för att arbeta med tabeller:

local frukter = {"äpple", "banan", "apelsin"}

-- Lägga till element i slutet
table.insert(frukter, "päron")         -- Lägger till päron i slutet
table.insert(frukter, 2, "kiwi")       -- Lägger till kiwi på position 2

-- Ta bort element
local borttagen = table.remove(frukter, 3)  -- Ta bort element på position 3, returnerar det borttagna elementet
print("Borttaget: " .. borttagen)

-- Sortera en tabell
table.sort(frukter)  -- Sorterar frukter i alfabetisk ordning

-- Konkatenera (sätta ihop) alla element till en sträng
local fruktLista = table.concat(frukter, ", ")
print(fruktLista)  -- Skriver ut t.ex.: "apelsin, banan, kiwi, päron"

Övningar

Övning 1: Shoppinglista

Skapa en shoppinglista med följande funktionalitet:

  1. Skapa en tom tabell för shoppinglistan
  2. Lägg till minst 5 olika varor med pris
  3. Skriv ut alla varor med deras priser
  4. Beräkna och skriv ut totalpriset för alla varor
  5. Sortera varorna i alfabetisk ordning och skriv ut dem igen

Lösningsförslag:

-- Shoppinglista med priser

-- Skapa en tom tabell för shoppinglistan
local shoppinglista = {}

-- Lägga till varor med priser
shoppinglista["mjölk"] = 15.90
shoppinglista["bröd"] = 24.50
shoppinglista["ägg"] = 32.00
shoppinglista["ost"] = 89.90
shoppinglista["kaffe"] = 45.00

-- Skriv ut alla varor med deras priser
print("Min shoppinglista:")
print("------------------")
for vara, pris in pairs(shoppinglista) do
    print(vara .. ": " .. pris .. " kr")
end

-- Beräkna totalpriset
local totalpris = 0
for _, pris in pairs(shoppinglista) do
    totalpris = totalpris + pris
end
print("\nTotalpris: " .. string.format("%.2f", totalpris) .. " kr")

-- Sorterad lista (måste konvertera till array först eftersom pairs ger oordnad iteration)
print("\nSorterad lista:")
print("------------------")
local sorterad = {}
for vara, pris in pairs(shoppinglista) do
    table.insert(sorterad, {namn = vara, pris = pris})
end

-- Sortera på varunamn
table.sort(sorterad, function(a, b) return a.namn < b.namn end)

-- Skriv ut den sorterade listan
for _, item in ipairs(sorterad) do
    print(item.namn .. ": " .. item.pris .. " kr")
end

Övning 2: Minimatrix

Skapa en 3x3 matris (en nästlad tabell) och utför följande operationer:

  1. Fyll matrisen med tal (kan vara slumpmässiga eller valfria)
  2. Skriv ut matrisen på ett snyggt sätt (med rader och kolumner)
  3. Beräkna och skriv ut summan av alla tal i matrisen
  4. Beräkna och skriv ut medelvärdet av alla tal
  5. Hitta och skriv ut det största och minsta talet i matrisen

Lösningsförslag:

-- Skapa en 3x3 matris

-- Initialisera matrisen
local matris = {
    {7, 2, 9},
    {5, 1, 8},
    {3, 6, 4}
}

-- Skriv ut matrisen på ett snyggt sätt
print("Min 3x3 matris:")
print("--------------")
for i = 1, 3 do
    local rad = ""
    for j = 1, 3 do
        rad = rad .. string.format("%3d", matris[i][j])
    end
    print(rad)
end
print("--------------")

-- Beräkna summan
local summa = 0
local antal = 0
local störst = matris[1][1]  -- Anta att första elementet är störst
local minst = matris[1][1]   -- Anta att första elementet är minst

for i = 1, 3 do
    for j = 1, 3 do
        local värde = matris[i][j]
        summa = summa + värde
        antal = antal + 1
        
        -- Uppdatera störst och minst
        if värde > störst then
            störst = värde
        end
        if värde < minst then
            minst = värde
        end
    end
end

-- Beräkna medelvärde
local medelvärde = summa / antal

-- Skriv ut resultaten
print("Summa: " .. summa)
print("Medelvärde: " .. string.format("%.2f", medelvärde))
print("Största talet: " .. störst)
print("Minsta talet: " .. minst)