Tables
Tables are the only data structure in LuaLuaA lightweight, embeddable scripting language used as the primary scripting language in FiveM server development.. They implement associative arrays — any non-nil, non-NaN value can be a key.
Creating tables
-- Empty table
local t = {}
-- List-style (integer keys 1, 2, 3...)
local colors = {"red", "green", "blue"}
-- Record-style (string keys)
local point = {x = 10, y = 20}
-- Mixed
local t = {
"first", -- [1]
"second", -- [2]
name = "example", -- ["name"]
[100] = "hundred", -- [100]
[true] = "yes", -- [true]
}
-- Expression keys (use brackets)
local t = {
[f(1)] = g,
["key with spaces"] = "value",
}
Accessing fields
t.key -- sugar for t["key"]
t["key"] -- explicit string key
t[1] -- integer key
t[expr] -- expression key
-- Reading nonexistent key → nil
print(t.missing) -- nil
Setting fields
t.key = "value" -- sugar for t["key"] = "value"
t["key"] = "value"
t[1] = "first"
t[new_key] = new_val
-- Setting to nil removes the key
t.key = nil -- key is removed from table
Sequences
A sequence is a table where the positive integer keys {1..n} are all non-nil, and key n+1 is nil (the "border").
local seq = {10, 20, 30} -- sequence of length 3
#seq -- 3
-- NOT a sequence (gap at index 2):
local not_seq = {10, nil, 30}
#not_seq -- 1 or 3 (UNDEFINED!)
[!warning]
#on non-sequences is undefined If your table has holes (nil between integers),#may return any border. Use explicit counting oripairsfor safety.
Iterating
ipairs — sequential integer keys
local t = {"a", "b", "c"}
for i, v in ipairs(t) do
print(i, v)
end
-- 1 a
-- 2 b
-- 3 c
-- Stops at first nil
pairs — all key-value pairs
local t = {x = 1, y = 2, z = 3}
for k, v in pairs(t) do
print(k, v)
end
-- Order is UNDEFINED (hash table iteration)
Numeric for (preferred for arrays)
local t = {10, 20, 30}
for i = 1, #t do
print(i, t[i])
end
Table operations
Insert / remove
local t = {1, 2, 3}
table.insert(t, 4) -- append: {1, 2, 3, 4}
table.insert(t, 2, 99) -- insert at pos 2: {1, 99, 2, 3, 4}
table.remove(t, 2) -- remove pos 2: {1, 2, 3, 4}
-- 5.4 shorthand for append
t[#t + 1] = 5
Sort
local t = {3, 1, 4, 1, 5, 9}
table.sort(t) -- ascending: {1, 1, 3, 4, 5, 9}
table.sort(t, function(a, b) return a > b end) -- descending
Concat
local t = {"hello", "world", "!"}
print(table.concat(t, " ")) -- "hello world !"
print(table.concat(t, ", ", 2)) -- "world, !" (from index 2)
Move (5.3+)
-- table.move(a1, f, e, t [,a2])
local src = {1, 2, 3, 4, 5}
local dst = {}
table.move(src, 1, 3, 1, dst) -- dst = {1, 2, 3}
Pack / unpack
local t = table.pack(1, 2, 3) -- {1, 2, 3, n=3}
print(t.n) -- 3
local a, b, c = table.unpack(t) -- 1, 2, 3
local a, b = table.unpack(t, 2) -- 2, 3 (from index 2)
Table as array
-- Build from loop
local squares = {}
for i = 1, 10 do
squares[i] = i * i
end
-- Build with table comprehension (Lua 5.4 doesn't have these,
-- use this pattern instead):
local t = {}
for i = 1, 5 do t[#t + 1] = i * 2 end
-- t = {2, 4, 6, 8, 10}
Table as record
local player = {
name = "Hero",
level = 10,
hp = 100,
inventory = {"sword", "shield"},
}
print(player.name) -- Hero
print(player.inventory[1]) -- sword
player.mp = 50 -- add new field
Table as set
local set = {}
set["Lua"] = true
set["Python"] = true
-- Check membership
if set["Lua"] then print("found") end
-- Remove
set["Lua"] = nil
-- Iterate
for k in pairs(set) do print(k) end
Table as graph / linked structure
local node1 = {value = 1}
local node2 = {value = 2}
local node3 = {value = 3}
node1.next = node2
node2.next = node3
node3.next = nil
-- Traverse
local n = node1
while n do
print(n.value)
n = n.next
end
Key types allowed
| Key type | Allowed | Notes |
|---|---|---|
| string | ✅ | Most common |
| number (integer/float) | ✅ | 1 and 1.0 are the same key |
| boolean | ✅ | true and false as keys |
| table | ✅ | Identity comparison |
| function | ✅ | Identity comparison |
| userdata | ✅ | Identity comparison |
| thread | ✅ | Identity comparison |
| nil | ❌ | Cannot be a key |
| NaN | ❌ | Cannot be a key |