16

Here's an example

local query = {}
query['count'] = 1
query['query'] = 2
for k,v in pairs(query) do
    print(k)
end

The above will print first query then count.

How can I make sure without adding an int index key that the key strings keep their order when I loop through the table?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
steven
  • 662
  • 1
  • 6
  • 13
  • With dictionary tables, I don't believe it'll keep the same order. If you're wanting to keep some order, I would suggest making a second indexed table with the fields in the order you want. Then loop through that table and call query[v] instead. – Josh Oct 08 '13 at 23:48

3 Answers3

14

I answered in comment, but I'm moving it here to give a better idea of what I'm talking about.

local queryindex = {"count", "query"}
local query = {}
query['count'] = 1
query['query'] = 2

for _,v in ipairs(queryindex) do
  print(query[v])
end
Josh
  • 3,225
  • 7
  • 30
  • 44
  • The body of your `for` loop will only print the numbers, you mean `print(v)`? – Yu Hao Oct 09 '13 at 01:20
  • No, I mean precisely what I answered. I'm assuming that query['count'] and query['query'] aren't really numbers, but strings, and he was just using numbers to demonstrate positioning. `print(v)` will only print 'count' or 'query', and not their values within the 'query' table. – Josh Oct 09 '13 at 02:27
  • This is not correct. ipairs() order elements in a table by *integer* keys, and will ignore those elements with keys are not integers. – Jinfeng Nov 02 '16 at 20:11
  • @Jinfeng, did you read the original question? This does exactly what the op wanted. Queryindex is indexed by numerical keys. – Josh Nov 02 '16 at 20:23
5

In Lua, only tables with 1-based consecutive integer keys (a.k.a. array tables) can be parsed in order.

So, if you want to parse a table t in order, what you do is:

  • collecting its keys into an array-like table
  • sorting that keys table
  • using the keys table to iterate over t.

Example:

function sortedKeys(query, sortFunction)
  local keys, len = {}, 0
  for k,_ in pairs(query) do
    len = len + 1
    keys[len] = k
  end
  table.sort(keys, sortFunction)
  return keys
end

...

local query = {}
query['count'] = 1
query['query'] = 2
for _,k in pairs(sortedKeys(query)) do
  print(k, query[k])
end

It's also possible to create an iterator to do this a bit more idiomatically, but I never had the need.

kikito
  • 51,734
  • 32
  • 149
  • 189
  • 1
    this sorts the keys in alphabetical order. I understood that it should keep their order like they where defined (that is also what I'm looking for) – iRaS Aug 21 '19 at 05:24
  • Shouldn't that be `ipairs(sortedKeys(query))`, or we are back at square one of the original problem? – PiQuer Jul 10 '23 at 06:40
3

As long as the value is guaranteed to be from 1, 2, 3, to some N without holes and without duplicate, like in your example, you can build a sequence using reversed key-value pair like this:

local seq = {}
for k,v in pairs(query) do
    seq[v] = k 
end

for _,v in ipairs(seq) do
    print(v)
end
Yu Hao
  • 119,891
  • 44
  • 235
  • 294