# Efficient way of getting 3 random items from a table

``````local GameMaps = {}

for _, v in pairs(Maps.Teams:GetChildren()) do
table.insert(GameMaps, v)
end

for _, v in pairs(Maps.FFA:GetChildren()) do
table.insert(GameMaps, v)
end

local RandomMap1 = GameMaps[math.random(1, #GameMaps)]
local RandomMap2 = GameMaps[math.random(1, #GameMaps)]
local RandomMap3 = GameMaps[math.random(1, #GameMaps)]
``````

This is what I currently got and it’s pretty bad. Main problem is, all 3 maps could technically be the same map, or 2 of the same map, etc. I want all 3 to be different maps. second problem, I don’t know if it’s just me, but going

``````local RandomMap1 = GameMaps[math.random(1, #GameMaps)]
local RandomMap2 = GameMaps[math.random(1, #GameMaps)]
local RandomMap3 = GameMaps[math.random(1, #GameMaps)]
``````

Just looks bad to me, I don’t know if there’s a cleaner way to do this though. I would have thought changing the 1 to 3 would work, but it still just picks 1 map

``````print(#GameMaps) -- prints 4
local RandomMap = GameMaps[math.random(3, #GameMaps)]
print(RandomMap) -- Only prints 1 map
``````
4 Likes
``````local RandomMap = table.remove(GameMaps, math.random(#GameMaps))
``````

`table.remove` both removes and returns the element from a table.

Please note you’ll need to refill the table when you want it to be able to pick the same elements again (such as when it runs out, or if it’s okay to have the same map in the next round just not in the same round). It’s also probably a good idea to check if the table is size 1, and if so just return the item in position 1 instead of trying to random a number from 1 to 1. This also provides a good time to refresh the table.

2 Likes

You would want to use a function, using variable stores the number making it the same each time

You’d need to make a new table with all of the maps and use `math.random` to get one map, then use `table.remove` to remove it from the table so that it can not be chosen again. You’d have to repeat this 2 more times to get the 3 maps

Here’s a function that easily does that:

``````function GetMaps(amt)
local chosenMaps = {}
-- Re-adding the values in a new table
local newTable = {}

for i,v in pairs(GameMaps) do
newTable[i] = v
end
-- Choosing maps
for i = 1, amount do
local r = math.random(1, #newTable)
chosenMaps[i] = newTable[r]
table.remove(newTable, r)
end

return chosenMaps
end
``````
11 Likes

Seems to solve 1 issue. Is there a cleaner way to pick like all 3 random maps without having to do

``````local RandomMap1 = table.remove(GameMaps, math.random(#GameMaps))
local RandomMap2 = table.remove(GameMaps, math.random(#GameMaps))
local RandomMap3 = table.remove(GameMaps, math.random(#GameMaps))
``````

As for the table being 1, etc. When the maps are being chosen, the table gets preset back to {}

``````	local GameMaps = {}

for _, v in pairs(Maps.Teams:GetChildren()) do
table.insert(GameMaps, v)
end

for _, v in pairs(Maps.FFA:GetChildren()) do
table.insert(GameMaps, v)
end

local RandomMap1 = table.remove(GameMaps, math.random(#GameMaps))
local RandomMap2 = table.remove(GameMaps, math.random(#GameMaps))
local RandomMap3 = table.remove(GameMaps, math.random(#GameMaps))

print(RandomMap1, RandomMap2, RandomMap3)
``````

Yes, there’s much cleaner solution to the problem and way more efficient than the other solutions here. Generate a random permutation of numbers from 1 to #GameMaps and then choose the maps as in the example:

``````function randomPermutation(n)
assert(n >= 1, "n must be >= 1")
assert(n == math.floor(n), "n must be an integer")

local tab = {}
for i = 1, n do
tab[i] = i
end

for i = 2, n do
local randomIndex = math.random(i)
tab[randomIndex], tab[i] = tab[i], tab[randomIndex]
end

return tab
end

local permutation = randomPermutation(#GameMaps)
local map1 = GameMaps[permutation[1]]
local map2 = GameMaps[permutation[2]]
local map3 = GameMaps[permutation[3]]
``````

You can shuffle the map list to generate the order first so you don’t need to recreate a list again each time you draw the map.

``````function ShuffleList()
for i=1, #GameMaps - 1 do --change it to 3 if you just need to draw 3 maps
local listI = math.random(i, #GameMaps)
local temp = GameMaps[i]
GameMaps[i] = GameMaps[listI]
GameMaps[listI] = temp
end
end
``````

i typed these in phone, hope it is not wrong

4 Likes

Great idea to store the choices at the beginning. I think that this is the most efficient algorithm.

``````local temp = GameMaps[i]
``````GameMaps[i], GameMaps[listI] = GameMaps[listI], GameMaps[i]