Finding the closest number from a table

The Problem
Hi there! I’ve got a question, is it possible to find the closest number in a table from another number? So for example:

local numberTable = {5, 10, 15}
local number = 4

And that it prints the closest number from that table.

Thanks for reading and I hope you can help me out :slightly_smiling_face:

1 Like

This isn’t tested, but I hope it works for what you need.

local numberTable = {20, 11, 15} -- replace with your numbers
local number = 4
local closest = numberTable[1] -- arbitrary

for i, currentNum in pairs(numberTable) do
	
	local diff = math.abs(currentNum - number)
	
	if diff < closest then
		closest = currentNum
	end
	
end

print(closest)
1 Like

It works! Thanks! One question, how does this work?

Well first off, its a very hacky solution. I do not believe that it covers every usage case and I am not even sure if it REALLY works :sweat_smile:. What the code does is it loops through each number in numberTable, and then gets a difference between the target number and the current numberTable number. if the difference is less than the current closest number, then replace the current closest number with the current number (because it is closer to number). I can already think of several usage cases where this code doesn’t work, so I would definitely look into different ways of doing this.

Oh, alright. Still thanks for helping!

This checks if the difference is less than the previous number, not the previous distance. Did you mean something like this?

local closest = numberTable[1] 
-- everything before this is the same

for i, currentNum in pairs(numberTable) do
	
	local currentDiff, closestDiff = math.abs(currentNum - number), math.abs(closest - number)
	
	if currentDiff < closestDiff then
		closest = currentNum
	end
	
end
5 Likes

May I ask, why are you using pairs instead of ipairs for array iteration?

Alternativaly create a function for this just in case.

function find_closest(number_table, value)
    local closest;
    local closest_diff;
    for _, n in ipairs(number_table) do
      if math.abs(n - value) < closest then
         closest, closest_diff = n, math.abs(n - value);
      end;
    end;
    return closest;
end;

Alright, so, this isn’t exactly where I am looking for, it works, but after changing the value, it still shows the old one, I want the closest number in a table from a number, not if it is less than the previous number or distance.

Are you looping through the table again after changing it? Checking if two number’s difference is less than the other two’s difference is how you check if it’s “closer”.

2 Likes

Alright, so, I’ll just explain what I am trying to achieve to let it be more clear. I’m working on a level system, every 5 levels you get another rank, the max level is 100 so there are a lot of ranks. I tried to do this with tables, I am not sure if this is the best say, but then I look into the table for the closest number near the player’s level.

You can just round to the nearest 5. That way you won’t need to pre-define all the numbers in a table. Roblox recently added math.round(), so you can use this to make a function that rounds to the nearest 5.

local function round(number)
    return math.round(number / 5) * 5
end

Examples:
round(1) → 0
round(4) → 5
round(7) → 5
round(8) → 10

You might need to enable the Luau beta feature to be able to use math.round() though. If you don’t have access to this beta feature, you can alternatively use this function which doesn’t require math.round():

local function round(num)
    return math.floor(num / 5 + 0.5) * 5
end

You get the same results as the above tests. Using these functions prevent you from having to manually type all the numbers in the table and loop through it every time, so it’s much more efficient.

6 Likes

Thanks! It works! This is was where I was looking for!

1 Like