23. Tables as dictionaries
The table type used for lists also supports named keys. With names (strings) instead of positions (numbers), the table acts like a dictionary — a collection of facts about one thing.
Creating a dictionary
The literal syntax uses key = value inside the
braces:
local player = {
name = "Keiko",
level = 7,
hp = 95,
alive = true,
}The trailing comma is optional, but good style: it makes adding a field a one-line diff later.
Read values with dot notation or bracket notation:
print(player.name) -- Keiko
print(player["level"]) -- 7player.name and player["name"] are
identical. Use dot notation for a plain word; use brackets when the key
is in a variable or has spaces:
local field = "hp"
print(player[field]) -- 95 -- dot would not work hereAdding and changing fields
Assigning to a missing key creates it; assigning to an existing key
replaces it; assigning nil deletes it:
player.mana = 30 -- new field
player.hp = 100 -- replace
player.alive = nil -- deleteAfter those three lines, player holds name,
level, hp, mana.
Looping with pairs
pairs is the dictionary iterator. It yields every key
and value, in unspecified order:
for key, value in pairs(player) do
print(key, value)
endEvery field prints, but not necessarily in the order you wrote. If
you need a specific order, store the keys in a list and loop that — or
use ipairs with a list shape instead.
On a list, pairs does include the numeric keys, but in
no guaranteed order. For lists, always use ipairs; for
dictionaries, use pairs.
Checking if a key exists
A missing key looks up as nil, which gives you an easy
check:
if player.email then
print(player.email)
else
print("No email on file.")
endThis works because nil is falsy and any non-nil value is
truthy.
Nested tables
A table value can be another table — the standard way to build structured data:
local player = {
name = "Keiko",
position = { x = 0, y = 5, z = -3 },
inventory = {"sword", "potion", "map"},
}
print(player.position.x) -- 0
print(player.inventory[1]) -- swordIn Roblox, the in-game world is one big nested table of this shape.
game.Players.Keiko.Character is just a chain of dot lookups
walking the tree, so this chapter's skills apply directly.
Lists and dictionaries together
One table can hold both numeric and named keys at once:
local quest = {
"Speak to the elder",
"Collect 5 herbs",
"Return to camp",
name = "Healer's Errand",
reward = 50,
}
print(quest.name) -- Healer's Errand
print(quest[1]) -- Speak to the elder
print(#quest) -- 3 (only the list part counts)# and ipairs only see the list part;
pairs walks everything. Tangled-sounding but handy: one
table can hold both an ordered list of items and some side facts about
it.
Homework
Problem 1 — Player record
Open exercises/23/homework/01-player-record.lua. Build a
player table with at least these four keys: name (string),
class (string), level (number),
alive (boolean). Then loop with
for ... in pairs(...) to print every key and value, one per
line.
Problem 2 — Inventory weights
Open exercises/23/homework/02-inventory-weights.lua. A
table maps item names to weights (numbers). Compute and print the total
weight.
Problem 3 — Safe lookup
Open exercises/23/homework/03-safe-lookup.lua. Write
local function lookup(dict, key) that returns the value if
the key exists, else the string "(not found)". Test it with
three calls: one that hits, one that misses, and one where the key is
held in a variable.
Challenge — Word frequency
Open exercises/23/homework/04-word-frequency.lua. Given
a list of words (some repeated), build a dictionary mapping each unique
word to its count. Print the dictionary one pair per line.
Stuck or finished? Open the homework solutions page.