Help sorting a dictionary by value

I’m developing a system for a hockey game where the puck’s NetworkOwner is set to the player closest to the puck on the server. (I know that this causes a lot of problems locally but just ignore that)

To do this I constantly loop a function that gets the distances of all the players and adds them to a table like this:

local distances = {}
local GetPlayers = game.Players:GetPlayers()
local puck = workspace.ball

for i = 1, #GetPlayers do 
	local player = GetPlayers[i]
	local distance = (puck.Position - player.Character.HumanoidRootPart.Position).Magnitude 
	distances[distance] = player.Name -- Adds the distance into the dictionary and makes its value the player's name
end 

This adds the players into a dictionary with the distance from the puck as the first value and the player’s name as the second value. Here’s where I run into a problem: How would I effeciently get the smallest value in this dictionary? Could I use table.sort(distances) and then pull the first value, and if I did that how would I read the first value in the dictionary, since distances[1] will not return the first value?

Thank you :slight_smile:

Ok, after messing around for hours I came up with a somewhat inefficient solution by looping through all of the values and comparing them to a lowest value. Still, not sure if this is the best way but it works.

For the sorting algorithm to sort out the distances check out Wikipedia and this other post for the sorting efficiencies. I believe yours is selection sort as you loop through comparing with the lowest value but I forgot all my computer science knowledge so just check out the sorting diagrams.

In order to find the closest player once you have found the smallest distance you just input the value into the distance to name dictionary, you have obtained.

local smallestDistance --obtain it via sorting

local closestPlayer = distances[smallestDistance]

However, the issue is that there is a chance if players will somehow have the same distance towards the puck and so for that distance, only one name will be recorded according to how game.Players:GetPlayers() orders the list of players in the game which is unreliable, to say the least:

2 Likes

you could probably just use table.sort(distances) then use

for i,v in ipairs(distances)
 return {i,v} -- return player and distance
end

this will return the first value in the table (probably)

1 Like

I didn’t think of return, that’s really smart. Thank you :slight_smile: