Sorting a table by values, not index

Hello, I’ve been trying to sort the following table:

["Bushes"] = 8,
["Cart"] = 3,
["Crates"] = 9,
["Fences"] = 3,
["Fire Crystal"] = 17,

note that the above table is what is printed out when i run print(allRarities)

This is how I’ve set up my table:

local allRarities = {}

local function addElement(i,v)
	allRarities[i] = v["Rarity"]
end

I’ve given it a few shots myself and looked at other topics but nothing will work. The closest I’ve gotten is probably this:

table.sort(allRarities,
	function(a,b)
		return a[2] > b[2]
	end
)

for i,v in pairs(allRarities) do
	print(i .. " " .. v)
end

but it seems to me like it’s either

  1. not doing anything
  2. just sorting the indexes by alphabetical order.

I tried to reverse the index and values in my table, however some indexes have the same value:

["Crates"] = 9,
["Torches"] = 9,

so I don’t think this is doable. Any help at all would be greatly appreciated!

Here’s my expected output:

["Cart"] = 3,
["Fences"] = 3,
["Bushes"] = 8,
["Crates"] = 9,
["Fire Crystal"] = 17,

As your data is in a dictionary, it is unordered, hence why table.sort() doesn’t do the required outcome. However, I will try and create something that will result in the desired order being achieved. Might take me a bit though…

edit:
Found this post here:

Their code is:

local array = {}
for key, value in pairs(dictionary) do
	array[#array+1] = {key = key, value = value}
end
table.sort(array, function(a, b)
	return a.value > b.value
end)
1 Like

A dictionary has no inherent order, an array does. You have to create the “sorting” functionality in your own way, and there’s not just one way to do it either. Examine your use case.

If you want to get technical, Lua’s hashing function (I believe it’s modulo based in source Lua) knows the order of the indices. But, that’s more work than anyone wants to be doing just for tables.

A possible solution, or else, use the above post

Instead, why not reverse the keys and values themselves? Because two different values can share the same key, just put them together in one array and make that the value.

-- example:
[3] = {"Cart"},
[9] = {"Crates", "Torches"}

Look at your use case and you might even be able to figure out something more efficient. Let’s compare against this method:

  • Let’s assume those numbers are costs, 3$, 9$. I want to know all items that do cost $3, now I have to go through every single table and look at the key. Instead, I can just index [3] and now I have all the items that do cost $3.
  • Well even if you don’t need that feature, it’s a bonus feature. You’ll still have to look through every value just to find what you want, unless your dictionary doesn’t have just numbers as values.

(Just to be clear, outside this use case, that post is still a good method to “sort dictionaries” entirely)

If you want to look up the cost of an item, yes, this is not the best approach. But at that point, you have your original dictionary for a reason. Why do you want it sorted?

1 Like

Hey everyone, thanks for the responses!

I’ve just fixed mine with the help of a friend. To everyone else trying to do this, the issue was that you cannot use table.sort on a table with string indexes.

I used a proxy array where I temporarily stored all the values I wanted to sort, and then sorted my original array with the keys that the proxy array used.

Here’s my code below, I hope you find it useful for your own games. As always, make sure you learn from the code and don’t just copy paste it.

local dictionary = require(game.ReplicatedStorage.Dictionary)
local allRarities = {}
local tempKeys = {}

-- Adds the elements with rarity into array allRarities
for i,v in pairs(dictionary["elements"]) do
	allRarities[i] = v.Rarity
end

-- Inserts keys into proxy array
for key, _ in pairs(allRarities) do
	table.insert(tempKeys, key)
end

-- Sorts the new proxy array
table.sort(tempKeys, function(a, b)
	return allRarities[a] < allRarities[b]
end)

-- Sorts allRarities array by the sort of proxy array
for _, item in ipairs(tempKeys) do
	local itemData = allRarities[item]
	print(item, itemData)
end

This is a very interesting way of addressing the problem. I appreciate this solution and will likely use it for something a little bit different in future where players can lookup rarities and sort by that. Thanks for the reply!

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