How can I get a percentage of elements from a table?

Hello! I would like to know if it’s possible to receive a percentage of elements from a table.
In other words, let’s say we have a table with length n. I want to get p% of the elements in this table. So if p==50 and n==4, I would want to get two of the elements. (preferably two random elements)

Currently, the way I would be doing this is something along the lines of this: (this also shows why I want to do it)

			local percentage = 50
			local plrs = game.Players:GetPlayers() --we will alter this table later on
			local selectedPlrs = {} --place the selected players in here
			for _ = 1,math.floor(#plrs/(100/percentage)) do --get the amount of players according to the percentage given
				local random = math.random(1,#plrs) --get a random number based off of plrs table
				table.insert(selectedPlrs,plrs[random]) --place the randomly selected player into selectedPlrs
				table.remove(plrs,random) --remove it from the table so it doesn't get selected twice
			end

But this just feels… oddly unnecessary? I would like to know if there’s a better way to do it.

(Sorry in advance if I shouldn’t post stuff when I basically already have a working script… lol)

If the script works fine but needs improving: #help-and-feedback:code-review :wink:

--note, this means you must not have an element as nil
local function getPercentageElements(t, percentage)
    local newT = t
    Random.new():Shuffle(newT)
    percentage = math.floor(math.clamp(tonumber(percentage) and math.floor(tonumber(percentage)) or 100, 0, 100)/100*#t)
    return percentage == 0 and {} or table.pack(table.unpack(t, 1, percentage))
end

print(getPercentageElements({5, 6, 1, 2}, 50))

I haven’t necessarily tested it, but it looks like it might work.

1 Like

So you want to get x random element/s from a table based on the percentage (p) of the total elements on the table (n).

local percentage = 0.5 -- 50 != 50%
local players = game.Players:GetPlayers():: {Player}
local totalNumOfPlayers = #players
local totalToGet = math.floor(totalNumOfPlayers * percentage) -- change if you don't want `math.floor`
local selectedPlayers = {}:: {Player?}

function getUniqueRandomNumbers(min: number, max: number, total: number)
    if total <= 0 then
        return {}
    end

	if max - min + 1 < total then
		error("Too few numbers in range to meet the total unique requirement.")
	end

	local numbers = {}
	for i = min, max do
		table.insert(numbers, i)
	end

	local selected = {}
	for i = 1, total do
		local index = math.random(1, #numbers)
		table.insert(selected, numbers[index])
		table.remove(numbers, index)
	end

	return selected
end

for _, i in getUniqueRandomNumbers(1, totalNumOfPlayers, totalToGet) do
	table.insert(selectedPlayers, players[i])
end

return selectedPlayers

So you do something like this I believe:

local t = { Elements blah blah blah }
t[math.random(1, #plrs)] -- Random index

I wasn’t aware of the Shuffle method, that actually helps alot. By the way, from my understanding you have to do Random.new():Shuffle(table) :slight_smile:

This does work, although I’ve had to make a few changes to the rest of my code, but that’s okay.
The issue I was having is made clear by the documentation for table.pack(): “Returns a new table with all arguments stored into keys 1, 2, etc. and with a field “n” with the total number of arguments.

It was adding on some other element to the table that I believe is just the length of the table. Not sure what the point of it is.

Again, this doesn’t need to be fixed as I’ve already done so myself. Thanks so much!
(for anyone coming from the future, in my case simply doing “t[“n”] = nil” works.)

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.