How to make a table of random values that doesn't repeat?

I am making a game, that contains maps made of different sublevels. The sublevels are placing randomly to make the order of minigames random. But I don’t know how to make them generate without repeating. I’ve tried using this script:

local sectionsCount = #game.ServerStorage.Maps["Map"..chosenMap]:GetChildren() - 2
local sectionsPlaced = {}
local sectionsPlacedCount = 0
local extra = false

table.insert(sectionsPlaced, 1) -- The first sublevel is always the same

while sectionsPlacedCount < sectionsCount do
	local selectedSection = math.random(2, sectionsCount)

	extra = false

	for i, v in pairs(sectionsPlaced) do
		if sectionsPlaced[i] == selectedSection then
			extra = true
		end
	end

	if extra == false then
		table.insert(sectionsPlaced, selectedSection)
		sectionsPlacedCount = sectionsPlacedCount + 1
	end

	wait()
end

But my knowledge of tables is pretty weak, and the script doesn’t even work. How can I change the code to make it work properly?

3 Likes
local unused = 10 --sublevels
local usedNums = {[1] = 1} --default
local function getNum()
    task.wait()
    local newNum = math.random(2, unused) --number generated
    print("Generated: " .. newNum)

    for i, v in pairs(usedNums) do
        if v == newNum then
           getNum()
           break
        end
    end
    usedNums[#usedNums + 1] = newNum --set new number
    if #usedNums < unused then --check if not finished
        getNum()
    end
end
getNum()
1 Like

got one that’s even better

local maps = {}

for i=1,10 do 
	maps[i] = i
end

table.sort(maps,function()
	return if math.random(0,1)==0 then false else true
end)

print(maps)
local function generateRandomNumbersOfCountN(count)
	local randomNumbers = {}
	for index = 1, count do
		local randomNumber
		repeat
			randomNumber = math.random(count)
		until not table.find(randomNumbers, randomNumber)
		table.insert(randomNumbers, randomNumber)
	end
	return randomNumbers
end

local randomNumbers = generateRandomNumbersOfCountN(10)
print(table.concat(randomNumbers, " "))

Here’s a sample of 10 results.

image

3 Likes

This is still going to favor the original order, table.sort() doesn’t compare every value with every other value, it compares values in pairs.

Not to mention the callback function of table.sort() should be passed the two values being compared & return a comparison of those two values.

You would be correct if I used math.random(), but since I gave it the parameters 0,1 it will return an int between and including those numbers:

My code will run fine sometimes, however other times it’ll error: invalid order function for sorting

Your solution is really awesome for a list of numbers.
If you wanted to randomize a table a solution could be:

local module = {}

function module.tableCount(myTable :{}) :number
	local i = 0
	for k,v in pairs(myTable) do
		i+=1
	end
	return i
end

function module.tableGetRandomElement(myTable :{}) :(any, any)
	local count = module.tableCount(myTable)
	local stopOn = math.random(count)
	local i = 0
	for k,v in pairs(myTable) do
		i +=1
		if i == stopOn then
			return k,v
		end
	end
end

function module.tableShuffle(myTable :{})
	local values = {}
	for k,v in pairs(myTable) do
		table.insert(values,v)
	end
	for k in pairs(myTable) do
		local vn,newValue = module.tableGetRandomElement(values)
		myTable[k] = newValue
		values[vn] = nil
	end
	return myTable
end

print(module.tableShuffle({1,2,3,4,5,Dog="cat"}))

Yeah, ignore my comment about math.random() for some reason I thought you called it without arguments.

I’ve changed the wording of the other bits so as not to cause any confusion.

Here’s how you could have fixed the sorting function.

local maps = {}

for i=1,10 do 
	maps[i] = i
end

table.sort(maps,function(a, b)
	if math.random(0, 1) == 0 then return a > b else return a < b end
end)

print(table.concat(maps, " "))

What I meant by return one of the two values is return a comparison of one of the two values (should have clarified better in my previous reply).

1 Like

I understood, still wrong though take a look

  16:36:43.055  > print(1<2,true, (1<2 == true))  -  Studio
  16:36:43.056  true true true  -  Edit

all the sort function is asking you is should a be before b?
It doesn’t care if it’s higher or lower or if you even you do any comparison all it asks for is a yes or no.

If you give that a shot, sometimes it’ll error.

By comparison I’m inferring to a boolean expression.

I wouldn’t advise that method anyway (as I previously stated there’s a bias in the ordering of the values).