Getting table.sort to sort through a players score

function FFAManager:GetWinningPlayer()
	local WinningPlayer = nil
	
	local SortedTable = table.sort(FFAScores, function(a, b)
		return a[1] > b[1]
	end)
	
	for _, v in pairs(SortedTable) do -- ERROR
		print(v[1] .. ' score is ' .. v[2]) -- Should print 'Player1 score is 1'
	end
	
	return WinningPlayer
end

[bad argument #1 (table expected, got nil)]
If I put print(FFAScores) then that prints a table, so it’s definitely a table. So not sure why SortedTable is returning nil

table.sort doesn’t return anything its almost like a function that simply sorts a table and doesn’t return , so therefor SortedTable will always be nil
Instead of setting table.sort to a value try something like this:

local SortedTable =FFAScores ---"copy" the table
 table.sort(SortedTable, function(a, b) ---sort it
		return a[1] > b[1]
	end)

for _, v in pairs(SortedTable) do
		print(v[1] .. ' score is ' .. v[2]) 
	end``
1 Like
function FFAManager:GetWinningPlayer()
	local WinningPlayer = nil
	print(FFAScores)
	local SortedTable = FFAScores
		table.sort(SortedTable, function(a, b)
			
		return a[1] > b[1]
	end)
	
	for _, v in pairs(SortedTable) do
		print(v[1] .. ' score is ' .. v[2]) -- Error here
	end
	
	return WinningPlayer
end

attempt to index number with number

What are the elements in SortedTable? Are they just numbers or are they tables? Anonymous function function(a,b) will contain values a and b that are being sorted from table SortedTable.

function FFAManager:OrganizePlayers()
	for _, player in pairs(Players:GetPlayers()) do
		if player.Parent then
			FFAScores[player] = 0
		end
	end
end

Change function(a, b) return a[1] > b[1] to function(a, b) return a > b

function FFAManager:GetWinningPlayer()
	local WinningPlayer = nil
	local SortedTable = FFAScores
	
	table.sort(SortedTable, function(a, b)	
		return a > b
	end)
	
	for _, v in pairs(SortedTable) do
		print(v[1] .. ' score is ' .. v[2]) -- Error
	end
	
	return WinningPlayer
end

attempt to index number with number

for _, v in pairs(SortedTable) do
		print(v[1] .. ' score is ' .. v[2]) -- Error
end

Value ‘v’ is just a number. Change _ to i so that you can use the iterator key, and then print(i .. " score = " .. v)

You have a table of scores with the player being the key. Key = Player, Value = Score.

Fixed code:

for i, v in pairs(SortedTable) do
		print(tostring(i) .. ' score is ' .. v) -- Error
end
3 Likes

i believe the problem here is how your table is setup try something like this instead:

function FFAManager:OrganizePlayers()
	for _, player in pairs(Players:GetPlayers()) do
		if player.Parent then
			FFAScores[player] = 0
		end
	end
end

function FFAManager:GetWinningPlayer()
	local WinningPlayer = nil
	print(FFAScores)
	local SortedTable = FFAScores
		table.sort(SortedTable, function(a, b)
			
		return a > b
	end)
	
	for _, v in pairs(SortedTable) do
		print( _.. ' score is ' .. v) 
	end
	
	return WinningPlayer
end

That seems to work :smiley: But I just realised I was never actually setting the ‘WinningPlayer’ variable. Would just doing

for i, v in pairs(SortedTable) do
	return i -- Would return the player that one
end

That way I only get the highest player, so I know they are the winner. Then could I just do this as well,

for i, v in pairs(SortedTable) do
    if not WinningPlayer then
        WinningPlayer = i
    end
    ScoreEvent:FireClient(i, v)
end

So I can get the Winner, but could also fire a RemoteEvent with the players score??

What do you want to RemoteEvent to do? Do you only want to fire to the winner or to everyone?

Last time I checked, table.sort doesn’t return anything. Wouldn’t it be like this?

function FFAManager:GetWinningPlayer()
	local WinningPlayer = nil
	table.sort(FFAScores, function(a, b)		
		return a > b
	end)
	
	return FFAScores[1]
end

Fire to all players. I’ll probably create another event to fire to everyone to show the winner, but I want an event to fire to the individual clients and tell them there score and what position they finished in

1 Like
local playerRankingNumerical = 1
for i, v in pairs(SortedTable) do
	ScoreEvent:FireClient(i, {score = v, ranking = playerRankingNumerical})
    playerRankingNumerical  = playerRankingNumerical  + 1
end
2 Likes

This might not be the best method but this might work:

-------------------------------------ServerScript
 local RemoteEvent = ---RemoteEvent

function GetFinalScores (Table) ---Table of scores values (not a table of tables)

table.sort(Table, function(a, b)		
		return a > b
   end)

RemoteEvent:FireAllClients(Table)---fire all clients and return just the table

 end

-------------------------------------Local Script



local function GetPos(Table, value) --- Convert strings indices into values
	local v = 0
	for _, val in pairs(Table) do
		v = v+ 1 
        if val == value then
	       return  v
      end
	end
end


 local RemoteEvent = ---RemoteEvent
local Player  = game.Players.LocalPlayer
RemoteEvent.OnClientEvent:Connect(function(Table)

local score = Table[Player] -- Get Score of Player
local position = GetPos(Table, score) -- Get Ranking


end

Edit: i kind of like @jody7777’s method a little better, as its a little more “clean” and “straight forward”

Can I ask why if I change the table it now doesn’t work?

function PlayerManager:SetupPlayerScores()
	for _, player in pairs(Players:GetPlayers()) do
		PlayerScoresTable[player] = {Points = 0, Kills = 0, Deaths = 0}
	end
end

function PlayerManager:GetPlayerScores()
	local WinningPlayer = nil
	local SortedTable = PlayerScoresTable
	local PlayerRankingNumerical = 1
print(#PlayerScoresTable) -- prints 0
	table.sort(SortedTable, function(a, b)	
		return a > b
	end)
	print(#SortedTable) -- prints 0
	for i, v in pairs(SortedTable) do
		if not WinningPlayer then
			WinningPlayer = i
		end
		print(PlayerRankingNumerical, v)
		PlayerScores:FireClient(i, PlayerRankingNumerical, v)
		
		PlayerRankingNumerical = PlayerRankingNumerical + 1
	end
	
	return WinningPlayer
end

I want to now make it include Points, Kills and Deaths. However, I only want to check points, not kills or deaths, but I don’t want to just do

PlayerScoresTable[player] = 0

As then I’d have to create a whole other table for kills and deaths. I’d rather keep it clean and simple and use the one table.

I don’t get any errors, and I don’t know why it won’t work

Don’t you have to change your sorting function to reflect these changes?

table.sort(SortedTable, function(a, b)	
		return a.Points  > b.Points
	end)

Also don’t forget since your are not sending just a number when you :FireClient, but instead a table( 3rd Argument v) , you have to change the script (local script) to work with tables

1 Like

You can’t sort dictionaries. table.sort doesn’t work like that because dictionary keys are sorted in a random order.

Edit: That’s wrong