Skip to main content

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 or ipairs for 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 typeAllowedNotes
stringMost common
number (integer/float)1 and 1.0 are the same key
booleantrue and false as keys
tableIdentity comparison
functionIdentity comparison
userdataIdentity comparison
threadIdentity comparison
nilCannot be a key
NaNCannot be a key