Advanced Tables
Prerequisites: The table library
Copying tables
Assignment copies a reference. To copy the contents:
local function shallowCopy(t)
local copy = {}
for k, v in pairs(t) do copy[k] = v end
return copy
end
local function deepCopy(t)
if type(t) ~= "table" then return t end
local copy = {}
for k, v in pairs(t) do copy[deepCopy(k)] = deepCopy(v) end
return copy
end
local original = {name = "Ada", tags = {"admin"}}
local shallow = shallowCopy(original)
local deep = deepCopy(original)
original.tags[1] = "changed"
print(shallow.tags[1])
print(deep.tags[1])
changed
admin
A shallow copy shares nested tables; a deep copy duplicates them.
(This simple deepCopy doesn't handle tables that contain themselves.)
Stacks and queues
local stack = {}
table.insert(stack, "a")
table.insert(stack, "b")
print(table.remove(stack))
local Queue = {first = 1, last = 0, items = {}}
local function push(q, v) q.last = q.last + 1; q.items[q.last] = v end
local function pop(q)
if q.first > q.last then return nil end
local v = q.items[q.first]
q.items[q.first] = nil
q.first = q.first + 1
return v
end
push(Queue, "x"); push(Queue, "y")
print(pop(Queue), pop(Queue), pop(Queue))
b
x y nil
table.remove(t, 1) also works as a queue, but it shifts every element;
the two-index version above is constant time.
Functional helpers
local function map(t, fn)
local r = {}
for i, v in ipairs(t) do r[i] = fn(v) end
return r
end
local function filter(t, pred)
local r = {}
for _, v in ipairs(t) do if pred(v) then r[#r + 1] = v end end
return r
end
local function reduce(t, fn, acc)
for _, v in ipairs(t) do acc = fn(acc, v) end
return acc
end
local nums = {1, 2, 3, 4, 5, 6}
local evens = filter(nums, function(n) return n % 2 == 0 end)
local squares = map(evens, function(n) return n * n end)
print(table.concat(squares, " "))
print(reduce(squares, function(a, b) return a + b end, 0))
4 16 36
56
Lua's standard library has none of these, so most projects write their own small set or use a library such as Penlight.
Grouping
local people = {
{name = "Ada", city = "London"}, {name = "Linus", city = "Helsinki"},
{name = "Alan", city = "London"},
}
local byCity = {}
for _, p in ipairs(people) do
byCity[p.city] = byCity[p.city] or {}
table.insert(byCity[p.city], p.name)
end
print(table.concat(byCity.London, ", "))
print(#byCity.Helsinki)
Ada, Alan
1