Jake
Jake

Reputation: 97

How to sort a table by its values in Lua?

I have a table consisting of key/value pairs:

mytable[a] = 1, 
mytable[b] = 4, 
mytable[r] = 7, 
mytable[f] = 2,

etc.

I want to sort the table by the numbers. So I'd like the table to be {(a, 1), (f, 2), (b, 4), (r, 7)} I've tried using

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

but that didn't seem to work... Thankyou

Upvotes: 4

Views: 5804

Answers (2)

lubgr
lubgr

Reputation: 38267

One way that is suggested in "Programming Lua" (I don't remember where exactly) is to extract the keys into a separate sequence, then sort the sequence, and use the resulting sorted sequence to index into the original table. Example:

keys = {}

for key, _ in pairs(mytable) do
    table.insert(keys, key)
end

table.sort(keys, function(keyLhs, keyRhs) return mytable[keyLhs] < mytable[keyRhs] end)

You can then iterate over the keys to retrieve the corresponding values:

for _, key in ipairs(keys) do
    print(key, mytable[key])
end

Upvotes: 5

Nicol Bolas
Nicol Bolas

Reputation: 473272

A table either is a set of key/value pairs or an array. OK, that's not entirely true; a table can be both, but the key/value entries will have no relationship to the array entries. That is, you can do this:

tbl = {
  ['a'] = 1,
  ['b'] = 4,
  [1] = {'a', 1},
  [2] = {'b', 4},
}

tbl[2] will have no direct relationship to tbl['b']. You can perform tbl[2] = <anything>, and it will have no effect on the contents of tbl['b'].

So long as the table doesn't change, you can take any pure key/value table and build an array part of it, which you can then sort however you like. Here's a function which does that:

local function build_array(tbl)
  --We cannot modify `tbl` while iterating through it, so build a temp array.
  local arr = {}
  for key, value in pairs(tbl) do
    arr[#arr + 1] = {key, value}
  end

  for ix, value in ipairs(arr) do
    tbl[ix] = value
  end

  return tbl
end

Upvotes: 3

Related Questions