Insert a random item into an array, only when it's not a duplicate

  1. What do you want to achieve?
    I need to loop through a list of variables and add random ones to another list, only if it doesnt already exist. However (and this is the part I can’t figure out), I need it to pick a new one from the list.

  2. What is the issue?
    Mentioned above, I cannot find out how to repeat the process efficiently

  3. What solutions have you tried so far?
    (see below)

for i = 1, 3 do
		local RandomSeed = math.random(1, #MapOptions)
		
		local function AddPosition(Position)
			if table.find(ChosenMaps, MapOptions[Position]) then
				local AvailablePositions = {}
				
				for _,NewPosition in ipairs(MapOptions) do
					if not table.find(ChosenMaps, NewPosition) then
						table.insert(AvailablePositions, NewPosition)
					end
				end
				
				local NewPosition = math.random(1, #AvailablePositions)
				
				table.insert(ChosenMaps, AvailablePositions[NewPosition])
			else
				
				table.insert(ChosenMaps, MapOptions[Position])
			end
		end
		
		AddPosition(RandomSeed)
	end

This is just trying to get 3 random maps and eventually just returns them.

1 Like

I apologize if I’m not understanding you very well as I’m a little confused by the wording.

Based on the variable names in your script as well as your request, it sounds like you want a script that generates a table of three maps that do NOT contain maps from a previous round. Is that correct?

No, just any 3 maps from a list (the list is just pulling some names from ServerStorage).

I would simply get the list of maps from ServerStorage and then run it through a table randomizer function. Then pick the first three.

local ServerStorage = game:GetService("ServerStorage")
local maps = ServerStorage.Maps:GetChildren()

local function randomizeTable(tbl) --Credit to StickMasterLuke for this randomizer, it's very useful
	local returntbl={}
	if tbl[1]~=nil then
		for i=1,#tbl do
			table.insert(returntbl,math.random(1,#returntbl+1),tbl[i])
		end
	end
	return returntbl
end

local function pickRandomMaps()
    local randomizedMaps = randomizeTable(maps)
    return {randomizedMaps[1], randomizedMaps[2], randomizedMaps[3]}
end

local pickMaps = pickRandomMaps() --Your 3 maps are here

Actually now that I think about it… this script can be simplified a whole lot

local ServerStorage = game:GetService("ServerStorage")
local maps = ServerStorage.Maps:GetChildren()

local function pickRandomMaps()
    local pickedMaps = {}
    for i = 1, 3 do
        table.insert(pickedMaps, math.random(1, #pickedMaps + 1), maps[i])
    end
    return pickedMaps
end

local pickMaps = pickRandomMaps()
1 Like

Awesome, I don’t really understand what’s happening in the randomizeTable function mainly where you’re inserting the table, can you run me through it?

To compound upon this I would probably use a simple insert randomizer such as this one:

function randomizeTable(list)
    local tbl = {}
    for i = 1,#list do
        table.insert(tbl,math.random(1,#tbl+1),list[i])
    end
    return tbl
end
1 Like

Thank you both for your help, I think this all makes sense now.

The table.insert function has an optional middle parameter where you can specify where in a table a certain value is inserted into. If left nil, it defaults to the every next value after the last value in a table. This is the key to making it work.

In the table.insert(pickedMaps, math.random(1, #pickedMaps + 1), maps[i]) line, you’ll notice that the middle parameter is a random number between 1 and the number of objects in the pickedMaps table. This makes it so that when the objects are copied over to the new table, they’re inserted in gradually more random ways per loop.

1 Like

Oh actually, I just tested this multiple times, it only returns the first three values in the maps array in different orders e.g.

First Time:
Map1, Map3, Map2

Second Time:
Map1, Map2, Map3

Third Time:
Map2, Map1, Map3

And so on, is there any fix to this, there are quite a few maps.

1 Like

I’m guessing my simplified version was wrong. Are you using my first script or the second one? If you’re using the second one then try the first one as that one shouldn’t return only the first three.

If that still doesn’t work, perhaps try it this way, where the maps are randomized and preserved every time the function is called and the last three maps are chosen instead of the first three:

local ServerStorage = game:GetService("ServerStorage")
local maps = ServerStorage.Maps:GetChildren()

local function randomizeTable(tbl) --Credit to StickMasterLuke for this randomizer, it's very useful
	local returntbl={}
    for i=1,#tbl do
		table.insert(returntbl,math.random(1,#returntbl+1),tbl[i])
	end
	return returntbl
end

local function pickRandomMaps()
    maps = randomizeTable(maps) --Randomize the maps table every time
    return {maps[#maps - 2], maps[#maps - 1], maps[#maps}
end

local pickMaps = pickRandomMaps() --Your 3 maps are here
1 Like

I tried this to start with, must have messed something up, works perfectly now, thank you :slightly_smiling_face:

1 Like