Search code examples
loopslualua-table

How to loop through the table and keep the order?


I got the following table set:

local a = {
    [12 * 30 * 24 * 60 * 60]  =  'year',
    [30 * 24 * 60 * 60]       =  'month',
    [24 * 60 * 60]            =  'day',
    [60 * 60]                 =  'hour',
    [60]                      =  'minute',
    [1]                       =  'second'
}

However, when I pair loop over it and print key, value I get this:

for seconds, str in pairs(a) do
    print (seconds, str)
end
----------
31104000    year
60          minute
3600        hour
1           second
2592000     month
86400       day

As you can see, the order is completely messed up. How can I loop over the table and keep the order?


Solution

  • You are laboring under a misconception:
    Lua tables explicitly do not preserve the order in which elements were entered, so there is no way to refer to that order after the fact.
    (under the hood, they are currently a hybrid of an array and a hash-map)

    What you probably actually want (going after your provided example), is iterating the elements ordered by the key.
    That is certainly possible, but requires a custom iteratorator.

    How iterators work:
    what is actual implementation of lua __pairs?
    Difference between stateful and stateless iterators in Lua

    function sorted_iter(t)
      local i = {}
      for k in next, t do
        table.insert(i, k)
      end
      table.sort(i)
      return function()
        local k = table.remove(i)
        if k ~= nil then
          return k, t[k]
        end
      end
    end
    

    Thus, your loop becomes:

    for seconds, str in sorted_iter(a) do
        print (seconds, str)
    end