Lists
Lesson 6.1
Tables are Lua’s only data structure. The simplest way to use one is as a list: values stored in order under the numbers 1, 2, 3 and so on.
Making a list
Curly braces create a table. Values separated by commas become a list:
local hotbar = { "Sword", "Pickaxe", "Torch" }
local empty = {}
Get a value by its position, called the index, in square brackets:
local hotbar = { "Sword", "Pickaxe", "Torch" }
print(hotbar[1]) --> Sword
print(hotbar[3]) --> Torch
print(hotbar[4]) --> nil
Lists start at 1
In Lua the first item is at index 1, not 0. Most other languages start at 0, so this trips up people who know them. All of Lua’s own functions expect lists that start at 1.
Reading an index that doesn’t exist gives nil, not an error.
Changing and adding
Assign to an index to change it:
local hotbar = { "Sword", "Pickaxe", "Torch" }
hotbar[2] = "Axe"
print(hotbar[2]) --> Axe
Length
# gives the number of items:
local hotbar = { "Sword", "Pickaxe", "Torch" }
print(#hotbar) --> 3
So the last item is hotbar[#hotbar], and you add an item to the end with hotbar[#hotbar + 1] = value.
The table library
The table library has functions for lists.
table.insert(list, value) adds to the end. table.insert(list, pos, value) inserts at a position and moves the rest up:
local queue = { "Alex", "Steve" }
table.insert(queue, "Noor") -- at the end
table.insert(queue, 1, "Kai") -- at the front
print(table.concat(queue, ", ")) --> Kai, Alex, Steve, Noor
table.remove(list) removes the last item and returns it. table.remove(list, pos) removes the item at a position and moves the rest down:
local queue = { "Kai", "Alex", "Steve" }
local first = table.remove(queue, 1)
print(first) --> Kai
print(table.concat(queue, ", ")) --> Alex, Steve
table.concat(list, sep) joins a list of strings or numbers into one string, as you saw above. It is much faster than joining with .. in a loop.
table.sort(list) sorts a list in place, smallest first:
local levels = { 12, 3, 30, 7 }
table.sort(levels)
print(table.concat(levels, " ")) --> 3 7 12 30
To sort in a different order, pass a function that says whether a should come before b:
local levels = { 12, 3, 30, 7 }
table.sort(levels, function(a, b) return a > b end)
print(table.concat(levels, " ")) --> 30 12 7 3
The function must give a strict answer: a > b, never a >= b. With >=, table.sort can fail with invalid order function for sorting.
Looping over a list
ipairs gives each index and value in order:
local drops = { "Bone", "Arrow", "Bow" }
for i, item in ipairs(drops) do
print(i, item)
end
1 Bone
2 Arrow
3 Bow
A numeric for works too, and lets you go backwards:
local drops = { "Bone", "Arrow", "Bow" }
for i = #drops, 1, -1 do
print(drops[i])
end
Bow
Arrow
Bone
Going backwards is the safe way to remove items while looping, because removing an item shifts the ones after it, not the ones before:
local inventory = { "Dirt", "Diamond", "Dirt", "Torch" }
for i = #inventory, 1, -1 do
if inventory[i] == "Dirt" then
table.remove(inventory, i)
end
end
print(table.concat(inventory, ", ")) --> Diamond, Torch
Holes break the length
A list should have no gaps. If you set an item in the middle to nil, the table has a hole, and # may give either side of it. ipairs stops at the first nil:
local t = { "a", "b", "c" }
t[2] = nil
for i, v in ipairs(t) do
print(i, v)
end
--> 1 a
To delete from a list, use table.remove, which closes the gap. If you really need empty slots (like a 36-slot inventory), store a placeholder such as false instead of nil, or keep the size in a separate variable.
Lists of anything
A list can hold any values, mixed types included, and even other tables:
local grid = {
{ 1, 0, 1 },
{ 0, 1, 0 },
}
print(grid[2][2]) --> 1
print(#grid, #grid[1]) --> 2 3
Try it
Make a list of five mob names. Add "Warden" at the end, remove the second mob, sort the list alphabetically, and print it joined with " | ". Then print how many mobs are in it.
Show a solution
local mobs = { "Zombie", "Creeper", "Skeleton", "Spider", "Enderman" }
table.insert(mobs, "Warden")
table.remove(mobs, 2)
table.sort(mobs)
print(table.concat(mobs, " | ")) --> Enderman | Skeleton | Spider | Warden | Zombie
print(#mobs) --> 5
Recap: { a, b, c } makes a list, indexes start at 1, # gives the length, ipairs loops in order, and the table library inserts, removes, joins and sorts.