6.2.3 Table

Concatenation

For an array containing only string and number values, returns a string of all values appended together. If a separator is specified, each value is delimited by the separator. Ignores key-value pairs.

Lua
local fruits = {"apple", "orange", "banana"}
local out = table.concat(fruits)
print(out) --appleorangebanana

local list = {["one"] = 150, ["two"] = 253, ["three"] = 368, 140, 216, 323}
local out = table.concat(list, ",")
print(out) --140,216,323

Sorting

The table.sort function sorts an array based on its values. Sorting is done in-place and does not return a value.

Lua
local list = {233, 37, 81, 351, 377, 56, 178}
table.sort(list)
print(list)
--[1] = 37,
--[2] = 56,
--[3] = 81,
--[4] = 178,
--[5] = 233,
--[6] = 351,
--[7] = 377

By default the function sorts by ascending order. You can define the type of comparison via an optional second argument in the form of a function.

It should accept two inputs, a and b, for comparison and return true if a will be sorted before b.

Lua
local function reverseOrder(a, b)
	return a > b
end

local list = {233, 37, 81, 351, 377, 56, 178}
table.sort(list, reverseOrder)
print(list)
--[1] = 377,
--[2] = 351,
--[3] = 233,
--[4] = 178,
--[5] = 81,
--[6] = 56,
--[7] = 37

Nested arrays cannot be directly compared so a function is required to define how to sort them.

Lua

local function sortByLastname(a, b)
	return a.last < b.last
end

local function sortByAge(a, b)
	return a.age < b.age
end

local members = {
	{["first"] = "Landry", ["last"] = "Tanner", ["age"] = 18},
	{["first"] = "Alec", ["last"] = "Chase", ["age"] = 23},
	{["first"] = "Angie", ["last"] = "McConnell", ["age"] = 30},
	{["first"] = "Rose", ["last"] = "Wright", ["age"] = 39},
	{["first"] = "Madden", ["last"] = "Fischer", ["age"] = 37},
	{["first"] = "Maci", ["last"] = "Ramos", ["age"] = 26},
	{["first"] = "Noelle", ["last"] = "Glenn", ["age"] = 19},
	{["first"] = "Blaire", ["last"] = "Mills", ["age"] = 36},
	{["first"] = "Ariella", ["last"] = "White", ["age"] = 19},
	{["first"] = "Helen", ["last"] = "Kline", ["age"] = 25},
	{["first"] = "Melvin", ["last"] = "Meyer", ["age"] = 22},
	{["first"] = "Danny", ["last"] = "Hobbs", ["age"] = 29},
	{["first"] = "Daniel", ["last"] = "Ferguson", ["age"] = 23}}
table.sort(members, sortByLastname)

for _, v in ipairs(members) do
	print(v["first"], v["last"], v["age"])
end
--Alec Chase 23
--Daniel Ferguson 23
--Madden Fischer 37
--Noelle Glenn 19
--Danny Hobbs 29
--Helen Kline 25
--Angie McConnell 30
--Melvin Meyer 22
--Blaire Mills 36
--Maci Ramos 26
--Landry Tanner 18
--Ariella White 19
--Rose Wright 39

table.sort(members, sortByAge)

for _, v in ipairs(members) do
	print(v["first"], v["last"], v["age"])
end
--Landry Tanner 18
--Ariella White 19
--Noelle Glenn 19
--Melvin Meyer 22
--Daniel Ferguson 23
--Alec Chase 23
--Helen Kline 25
--Maci Ramos 26
--Danny Hobbs 29
--Angie McConnell 30
--Blaire Mills 36
--Madden Fischer 37
--Rose Wright 39

Packing and Unpacking

A ‘tuple’ is an ordered collection of items.

When you pass multiple values into the print function with each element separated by a comma, you are creating a tuple. The same with when you initialize an array with a series of values.

Lua
local table = {154, 285, 364}
print("a", "b", "c")

The ‘table.unpack’ function returns a tuple of all the elements in an array in order.

Lua
local list = {1780, 290, 345, 42, 535}
print(table.unpack(list)) --1780 290 345 42 535

local a, b, c, d, e = table.unpack(list)
print(a, b, c, d, e) --1780 290 345 42 535

Conversely, the ‘table.pack’ function does the opposite by taking a series of values and returning a table containing all the elements in order. An element at key ‘n’ indicates the number of arguments including nil values.

Lua
local function someFn()
	return 134, 257, 366
end

local list = table.pack(someFn())
print(list)
--{
--	[1] = 134,
--	[2] = 257,
--	[3] = 366,
--	["n"] = 3
--}
Lua
local foo = table.pack(154, 295, 386, nil, 531, nil, 724)
print(foo)

-- [1] = 154,
-- [2] = 295,
-- [3] = 386,
-- [5] = 531,
-- [7] = 724,
-- ["n"] = 7

It is possible to attain a similar behavior by passing the tuple directly into a table, albeit, this does not assign the ‘n’ element.

Lua
local function someFn()
	return 134, 257, 366
end

local list = {someFn()}
print(list)
--{
--	[1] = 134,
--	[2] = 257,
--	[3] = 366
--}

Variadic functions

A variadic function is a function that can accept a variable and indefinite number of arguments.

This is different from “default” arguments in which missing arguments are filled in for you. And also different from “overloaded” functions in which the function behaves slightly differently based on the number or types of arguments you give it.

Both of those still require a defined number of arguments.

The print function is a variadic function for instance. Meaning any arbitrary number of arguments can be passed to the function and all of them will be printed out to the console.

Using “varargs,” parameters don’t need to be defined ahead of time in order for the function to reference an arbitrary number of arguments.

Instead, three dots ‘…’ are used to parameterize the tuple which can then be packed into a table.

Lua
function printSum(...)
	local sum = 0
	for _, v in ipairs({...}) do
		sum = sum + v
	end
	print(sum)
end
printSum(2, 4, 8, 16, 32, 64)
printSum(2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
--126
--129

It is still possible to define named parameters by placing them before the varargs. Any non-parameterized argument will then be passed to the vararg.

Lua
function printSum(numbers, ...)
	local sum = 0
	for _, v in ipairs({...}) do
		sum = sum + v
	end
	print(numbers, sum)
end
printSum("exponential", 2, 4, 8, 16, 32, 64)
printSum("primes", 2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
-- exponential 126
-- primes 129

And likewise, the vararg parameter can be passed along to additional functions.

Lua
local function qux(arg, ...)
	print(string.format("Now it's just another manic %s", arg))
end

local function baz(arg, ...)
	print(string.format("That's what I love about %s", arg))
	qux(...)
end

local function bar(arg, ...)
	print(string.format("%s night's alright for fighting", arg))
	baz(...)
end

local function foo(arg, ...)
	print(string.format("%s I'm in love", arg))
	bar(...)
end

local days = {
	"Friday",
	"Saturday",
	"Sunday",
	"Monday",
	"Tuesday",
	"Wednesday",
	"Thursday",
}
foo(table.unpack(days))

Insert and Remove

The ‘insert’ and ‘remove’ functions perform add or remove operations at the end of an array. Like the stack, these are sometimes referred to as a push (insert) or pop (remove) operation.

Lua
local list = {3.14, 42}
table.insert(list, "Hello")

print(list)
--[1] = 3.14,
--[2] = 42,
--[3] = "Hello"

Both functions can also take an optional position argument specifying the position to insert or remove a value.

Lua
local list = {3.14, 42, "world!"}
table.insert(list, 3, "Hello")
print(list)
--[1] = 3.14,
--[2] = 42,
--[3] = "Hello",
--[4] = "world!"
Lua
local list = {3.14, 42, "Hello", "world!"}
local value = table.remove(list, 3)

print(value)
print(list)
--Hello
--[1] = 3.14,
--[2] = 42,
--[3] = "world!"

Note that for these latter two operations, because values are not added or removed from the end of an array, proceeding elements must be shifted up or down to in order to adjust the size of the array.

For very large arrays, this copy-shift operation can take a not insignificant amount of time.

If your application requires constant insertion or removal from an arbitrary index with large arrays, consider using the key-value pair or some other data structure.