How Would You Get a Key When Given Just the Value; Dictionaries

Hi! In my current code, I have a dictionary that has a key with players name, which then gives a value that is their ranking. If I am given the value, how could I get the key from it?

When given [“PlayerOne”] = 1, how could I get “PlayerOne” from dictionary[1]?

Thanks!

I would just use:

table.insert(Table,{PlayerName,Number})

EDIT: This allows you to find the player name with Table[1] and the Value with Table[2]. It also gets rid of the length operator issues (not sure what they’re technically called) revolving around that.

You need to iterate over the dictionary until you find a matching value.
Example:

local dictionary = {
	["PlayerOne"] = 1,
}

local function getKeyFromValue(tab, input)
	for key, value in pairs(tab) do
		if value == input then
			return key
		end
	end
end

local key = getKeyFromValue(dictionary, 1)

That said, there are probably better solutions to your problem. Searching for a key based on a value might not always return what you want (because of things like float number inaccuracies), and if the dictionary is large, it can be slow. You might want to reconsider the way you store and interface with your player data.

3 Likes

Answering your lower question, it is handling a max of 12 player’s data instantaneously, then it removes it. This is in-game ranking, so after 120 seconds it disappears.

For some reason, the code is returning nil. I’m using it recursively while looping through the dictionary that is filled with players to numbers. Do you have any idea as to why it won’t work? Do you need any code?

If you are using anything other than integers, you may be running into floating point precisions errors and may want to include an epsilon in your query.

What types of values are you storing and what are you planning on using this for?

1 Like

Essentially, the game uses 3 variables to determine how well a player did. This comes out to the equation ab + c^2. Using this, I create a dictionary with the users name, and their Universal Ranking Value (URV) of the match. From there, I graphically represent it on UI, and then put it back into a loop to reward coins. For the sorting algorithm, I have to use the number as the key to make sorting easy, but because of that I’m not sure how I can do it the other way. Although as I write this, I can create 2 tables, inverses of eachother.

You could take advantage of a lookup table.

local dictionary = {}
local lookup = {}

dictionary[x] = y
lookup[y] = x

Then to get the key, you’d index the lookup table with the value.

1 Like

I’m attempting to do that, but am ending up with a nil value every time. I’m going to input the code, the looping has just been getting me with the different values. Thank you!

		    for i, player in pairs (players) do
				
						local userCoinsCollected = game.Players.PlayerURV:FindFirstChild(player.Name).CoinsCollected
					local userTimeSurvived = game.Players.PlayerURV:FindFirstChild(player.Name).TimeSurvived
					local userSurvived = game.Players.PlayerURV:FindFirstChild(player.Name).Survived
					
							game.Players.PlayerURV:FindFirstChild(player.Name).Value = userTimeSurvived.Value * userSurvived.Value + userCoinsCollected.Value * userCoinsCollected.Value
					print(game.Players.PlayerURV:FindFirstChild(player.Name).Value .. " is the URV")
					
					URVs[player.Name] = game.Players.PlayerURV:FindFirstChild(player.Name).Value
					print(URVs[player.Name])
					
			end
			
		table.sort(players, function(playerA, playerB)
	return URVs[playerA.Name] > URVs[playerB.Name]
		end)
		
	

local leaderboardFinal = {}
x = 1

for i, v in pairs(URVs) do
	
	print(URVs[i] .. "Testing")
	
	leaderboardFinal[URVs[i]] = x
	local key = getKeyFromValue(URVs, i)
	URVInverse[URVs[i]] = key

	x = x + 1
end
b = 1
for i, v in pairs(leaderboardFinal) do
print(i .. "is here")


	print(tostring(URVs[i]) .. "Gets " .. b .. " coins!" )
	--game.Players:FindFirstChild(key).leaderstats.Coins.Value = game.Players:FindFirstChild(key).leaderstats.Coins.Value + b
	b = b + 1
	
end

I use this solution quite a bit in my own code, however, in this case I can see a couple of major problems that you would have to overcome (and potential solutions):

Firstly, I don’t think he can use a function like this because two players can have the same rating and that could result in data loss as the table would just return the first matching value it sees. However, you could solve this problem by making a copy of the table and using table.remove until the function returns nil.

Also, as you mentioned yourself, floating point precision is an issue. I would not use use an epsilon because, in rare cases, you could end up matching the data incorrectly. Instead, I would round the players’ rank or use integers in the formula so that you can compare them using the ‘==’ operator.

1 Like

I don’t think he can use a lookup table this way because users could potentially have the same ranking meaning data may be lost. However, you could solve this by doing something like:

lookup[y] = lookup[y] or {}
table.insert(lookup[y], x)

And then iterating through that table to get all players with a certain ranking.

You can get that from a method called “next”. If I’m understanding you correctly, then this method should work.

function grabKey(tableGiven,keyFound)
    for key, value in next, tableGiven do
        print(key) --key is the name
        if keyFound==key then
            return key
        end
    end
end

Edit: forgot to add function.

This section appears to be where you’re going wrong.

for i, v in pairs(URVs) do
	print(URVs[i] .. "Testing")
	leaderboardFinal[URVs[i]] = x
	local key = getKeyFromValue(URVs, i)
	URVInverse[URVs[i]] = key
	x = x + 1
end

Instead, this will allow you to create the inverse table.

function invert(t)
	local i = {}
	for k, v in pairs(t) do
		i[v] = k
	end
	return i
end

Then you just call this method on the table you want the inverse of to invert it.

local inverseData = invert(data)

From here, would the table you access be inverseData, or does it just keep the current table.

I discussed this with Cheeky in DMS. He didn’t realise that you can access the values stored within tables.

I then gave and explained to him this snippet of code:

local a = {}
a["Player1"] = 10

for i,v in pairs(a) do
if v == 10 then
return i --Player1
end

And:

table.insert(a,{ID = 2837472, stat = 288})

he said he loved me <3

7 Likes

The solution you’ve proposed doesn’t work, at least, not completely. The following line will insert a table at the end of the a’s array part.

table.insert(a,{ID = 2837472, stat = 288})

To assign it to a specific index, do this instead.

a[index] = value

a[2837472] = 288

He didn’t actually need to assign to a specific index. He just needed to have a table with players data in it, and then be able to sort that table in numeric order.

1 Like