Nanfeng

Notes on software development, code, and curious ideas

How to Shuffle an Array in Lua

The Fisher–Yates algorithm shuffles an array uniformly in linear time. Starting at the last element, swap it with a random element at or before its position:

1
2
3
4
5
6
7
local function shuffle(items)
for i = #items, 2, -1 do
local j = math.random(i)
items[i], items[j] = items[j], items[i]
end
return items
end

This version modifies the input table. If the original order must be retained, copy the array first:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
local function shuffledCopy(items)
local result = {}
for i, value in ipairs(items) do
result[i] = value
end

for i = #result, 2, -1 do
local j = math.random(i)
result[i], result[j] = result[j], result[i]
end
return result
end

local original = { "a", "b", "c", "d" }
local randomOrder = shuffledCopy(original)
print(table.concat(randomOrder, ", "))

Lua arrays are conventionally indexed from 1, so math.random(i) is exactly the range needed. Choosing from 0 can produce a missing element, while repeatedly removing random elements adds unnecessary work and destroys the source array.

Seed policy depends on the Lua version and application. Recent Lua releases initialize randomness differently from older ones; on an older runtime, seed once during application startup rather than before every shuffle. For simulations and tests, an explicit fixed seed improves reproducibility. For security-sensitive selection, use a cryptographically secure random source instead of math.random.

+