Sort a Table[] in Lua
Asked Answered
V

2

34

I have a Lua table that I am trying to sort. The table's format is as follows:

tableOfKills[PlayerName] = NumberOfKills

Which means, for example, if I had a player named Robin with a total of 8 kills and another named Jon with a total of 10 kills, the table would be:

tableOfKills[Robin] = 8
tableOfKills[Jon]   = 10

How would I sort that type of table to show the highest kills first? Thanks in advance!

Vitriform answered 29/3, 2013 at 15:28 Comment(2)
possible duplicate of copying data from table to antoher with orderUnamuno
Table is not ordered array or something. It has no manifested order.Skillful
H
107

A table in Lua is a set of key-value mappings with unique keys. The pairs are stored in arbitrary order and therefore the table is not sorted in any way.

What you can do is iterate over the table in some order. The basic pairs gives you no guarantee of the order in which the keys are visited. Here is a customized version of pairs, which I called spairs because it iterates over the table in a sorted order:

function spairs(t, order)
    -- collect the keys
    local keys = {}
    for k in pairs(t) do keys[#keys+1] = k end

    -- if order function given, sort by it by passing the table and keys a, b,
    -- otherwise just sort the keys 
    if order then
        table.sort(keys, function(a,b) return order(t, a, b) end)
    else
        table.sort(keys)
    end

    -- return the iterator function
    local i = 0
    return function()
        i = i + 1
        if keys[i] then
            return keys[i], t[keys[i]]
        end
    end
end

Here is an example of use of such function:

HighScore = { Robin = 8, Jon = 10, Max = 11 }

-- basic usage, just sort by the keys
for k,v in spairs(HighScore) do
    print(k,v)
end
--> Jon     10
--> Max     11
--> Robin   8

-- this uses an custom sorting function ordering by score descending
for k,v in spairs(HighScore, function(t,a,b) return t[b] < t[a] end) do
    print(k,v)
end
--> Max     11
--> Jon     10
--> Robin   8
Honeysuckle answered 29/3, 2013 at 16:1 Comment(1)
+1 for an implementation of the spairs() iterator. Iterators are often a difficult concept to explain to new users, and well-explained examples in the wild will help mitigate that.Symphonize
U
0

An alternative way of sorting that avoids iterators and such is to pass the table to a list of key-value pairs (i.e.: list = {{k1,v1}, {k2, v2}, ...}. Here's my solution:

local ranks = {}
for player,kills in pairs(tableOfKills) do
    table.insert(ranks, {player, kills})
end

-- Now we use Lua's built-in sort function with a short custom comparator function:
table.sort(ranks, function (a, b) return a[2] > b[2] end)

-- The only thing left to do is display the results:
for i=1,#ranks do
    print(ranks[i][1], ranks[i][2])
end
Utmost answered 10/12, 2021 at 20:8 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Debauched

© 2022 - 2024 — McMap. All rights reserved.