Skip to content

Lua Arrays

In Lua, the concept of an “array” is typically implemented using tables with integer keys. These are ordered collections of objects. Arrays can be single-dimensional (a list) or multi-dimensional (like a table with rows and columns, often represented as a table of tables).

Lua tables, when used as arrays, do not have a fixed size. They can grow or shrink dynamically as needed, limited only by available memory. The convention in Lua is for arrays to be 1-indexed, meaning the first element is at index 1. The length operator # can be used to get the size of a sequence (an array with no gaps starting from index 1).

A single-dimensional array is a straightforward table with numeric indices. You can initialize and iterate through it using loops. By convention, Lua arrays start at index 1.

local my_array = {"Lua", "Tutorial"}
-- Iterate from 1 up to the length of the array
for i = 1, #my_array do
print(my_array[i])
end
-- Accessing an element at an unassigned index (e.g., 0 or 3 in this case)
print(my_array[0]) -- Lua convention is 1-based indexing
print(my_array[3])

When the above code is run, the output will be:

Lua
Tutorial
nil
nil

As shown, accessing an index that doesn’t hold a value (like my_array[0] or my_array[3] in this 1-indexed array of length 2) results in nil. While Lua’s convention is 1-based indexing (and functions like # and ipairs rely on this), tables can technically store values at any integer index, including 0 or negative numbers. Here’s an example using various indices:

local custom_indexed_array = {}
custom_indexed_array[-1] = "Negative One"
custom_indexed_array[0] = "Zero"
custom_indexed_array[1] = "One"
custom_indexed_array[2] = "Two"
print(custom_indexed_array[-1])
print(custom_indexed_array[0])
print(custom_indexed_array[1])
-- Note: The # operator might not give the expected count for non-sequence tables.
-- For iterating such tables, `pairs` might be more suitable than `ipairs`.

When the above code is run, the output will be:

Negative One
Zero
One

Common Pitfall: Using ipairs or the length operator # with arrays that are not 1-indexed sequences (i.e., arrays with nil values between elements, or not starting at index 1) can lead to unexpected results. ipairs iterates from 1 up to the first nil integer key. The # operator is reliable for sequences.

Multi-dimensional arrays are most commonly implemented in Lua as a table of tables (an array where each element is another array).

  • Table of tables (most common and idiomatic)
  • Single table with calculated indices (less common, for specific optimization scenarios)

Here’s an example of a 2x2 multi-dimensional array using the table-of-tables approach:

-- Initialize a 2x2 matrix (table of tables)
local matrix = {}
local num_rows = 2
local num_cols = 2
for i = 1, num_rows do
matrix[i] = {} -- Create a new row (which is a table)
for j = 1, num_cols do
matrix[i][j] = string.format("Row %d, Col %d", i, j)
end
end
-- Access and print elements
for i = 1, num_rows do
for j = 1, num_cols do
print(matrix[i][j])
end
end

When the above code is run, the output will be:

Row 1, Col 1
Row 1, Col 2
Row 2, Col 1
Row 2, Col 2

The alternative, manipulating indices in a single table, is less common for general use as it’s more complex to manage but can be used in performance-critical situations to optimize memory layout:

-- Initialize a 2x2 matrix using a single table and calculated indices
local flat_matrix = {}
local num_rows = 2
local num_cols = 2
for r = 1, num_rows do
for c = 1, num_cols do
-- Formula to map (r, c) to a single index
local index = (r - 1) * num_cols + c
flat_matrix[index] = string.format("Val at (%d,%d)", r, c)
end
end
-- Access and print elements
for r = 1, num_rows do
for c = 1, num_cols do
local index = (r - 1) * num_cols + c
print(flat_matrix[index])
end
end

When the above code is run, the output will be:

Val at (1,1)
Val at (1,2)
Val at (2,1)
Val at (2,2)

Lua’s tables are inherently sparse. If an index is not assigned a value, it doesn’t consume memory for that ‘slot’ (other than the general overhead of the table structure). This can be memory-efficient, especially for arrays or matrices where many elements might be nil or a default value.

Further Resources: For detailed information on tables and their usage as arrays, refer to the official Lua documentation.