For those that find this answer later, this will shuffle in place without making a new table:
local function ShuffleInPlace(t)
for i = #t, 2, -1 do
local j = math.random(i)
t[i], t[j] = t[j], t[i]
end
end
And this one that returns a shuffled table without touching the original (unlike the current answer, which both shuffles in-place and returns a copy):
local function Shuffle(t)
local s = {}
for i = 1, #t do s[i] = t[i] end
for i = #t, 2, -1 do
local j = math.random(i)
s[i], s[j] = s[j], s[i]
end
return s
end
Usage:
local t = {"a", "b", "c", "d", "e", "f"}
print(table.concat(t)) --> abcdef
local s = Shuffle(t)
print(table.concat(t)) --> abcdef (unchanged)
print(table.concat(s)) --> fbcade (shuffled)
ShuffleInPlace(t)
print(table.concat(t)) --> dcbfea (shuffled)
And a quick sanity check that they're uniform:
local t = {"a", "b", "c"}
local results = {abc = 0,acb = 0,bac = 0,bca = 0,cab = 0,cba = 0}
for i = 1, 10000000 do
ShuffleInPlace(t)
local r = table.concat(t)
results[r] = results[r] + 1
end
for k, v in pairs(results) do print(k, v) end
--[[
cba 1667473
cab 1666235
bca 1665672
bac 1666782
acb 1666447
abc 1667391
--]]