简体   繁体   中英

Ordered lua table looping using C API

Consider the following lua table:

foo = {
    bar1 = {a = 1, b = 2, c = "hello"},
    bar2 = {a = 5, b = 2, c = "bbq"},
    bar3 = {a = 76, b = 13, c = "pwnd"}
}

I am trying to iterate this table using the lua C API to retrieve the key names, bar1, bar2 and bar3. I used the lua_next(L, -2) function to iterate as suggested by many, but the problem is that it returns the elements in random order. The order changes on each run.

I use the following code:

for( lua_pushnil(L); lua_next(L, -2) != 0; lua_pop(L, 1) )
{
    printf("%s\n", lua_tostring(L, -2));
}

Most of the time, the output is unordered, such as bar2 bar1 bar3 . When lucky, it's ordered. Is there an easy way to loop the table keys in an ordered fashion? What would be the equivalent code as I use, but ordered? Thanks!

Edit:

I know I am using a map rather than an array. But in lua script we have ipairs which would work just fine for this case. I'm looking at the C API equivalent. I've found this stackoverflow answer which gives a different answer, but it doesn't work for me, so I wonder if that answer is good or relevant.

No. The order that Lua traverses tables is undefined.

If you know that the keys are of the form barXXX , then you can create these keys as strings dynamically in the order you wish and then get the corresponding value from the table.

Put the names in a C array, and then order them in C.

As others are saying, the order of keys returned by the hash portion of a table is not guaranteed.

Alternatively, use an array-like structure so you can use the array part:

foo = {
  {name = 'bar1', a = 1,  b = 2,  c = "hello"},
  {name = 'bar2', a = 5,  b = 2,  c = "bbq"},
  {name = 'bar3', a = 76, b = 13, c = "pwnd"}
}

So you can use ipairs or the equivalent to for i=1,#foo to iterate over the items in order.

Checking Lua's documentation, the main structure that Lua supports is a Hash Table . Given that it's always going to be a hash-table, you'd probably want to reimplement foo as an array . The bar1 , bar2 , etc can be part of the entry into the array like so:

foo = {}
foo[0] = {name='bar1', ...}
foo[1] = {name='bar2', ...}
    ...

or as @lhf suggested, just build the bar names inside a for-loop (if you know it's in sequence) and retrieve the values from foo table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM