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!

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
sgtaziz
  • 383
  • 1
  • 3
  • 6
  • 1
    possible duplicate of [copying data from table to antoher with order](http://stackoverflow.com/questions/5153642/copying-data-from-table-to-antoher-with-order) – finnw Mar 29 '13 at 15:35
  • Table is not ordered array or something. It has no manifested order. – SwiftMango Mar 29 '13 at 19:15

2 Answers2

105

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
Michal Kottman
  • 16,375
  • 3
  • 47
  • 62
  • 6
    +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. – RBerteig Apr 03 '13 at 20:15
-1

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
Ethan
  • 1
  • 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](/help/how-to-answer). – Community Dec 11 '21 at 02:49