如何在C API中生成ipairs(而不是成对)行为

在Lua中, pairsipairs可以以不同的顺序迭代相同的元素:

 > t = {[1]=1, [2]=2, [3]=3} > for k,v in pairs(t) do print(k,v) end 2 2 1 1 3 3 > for k,v in ipairs(t) do print(k,v) end 1 1 2 2 3 3 

当使用C API时,我只看到一个用于迭代表的工具: lua_next()函数,它的行为非常像pairs() Lua函数,它产生上面显示的2-1-3顺序。

我正在寻找一种有效的C方法,用于顺序迭代表的整数键(ipairs的C API版本)。

天真地,我考虑过:

 int tableLength = luaL_len(L, tableIndex); for (i=0, i++, i>tableLength){ // if t[i] is not null ... } 

但我不清楚表大小与连续整数键数不匹配的潜在性能问题:

 t = {[1]=1, [2]=2, [4]=4} -- has a (reported) length of 4 t = {[1]=1, [2]=2, [40000]=4} -- has a (reported) length of 2 

如果这确实是ipairs的方式,那么是否有一种简单的方法可以开始使用lua_next和最后找到的整数键继续遍历表的其余部分,避免再次遍历整数键部分? 这样做有两次我会看到一些整数键吗?

您只需使用rawgeti,直到获得nil密钥:

 // Tabs is on top of stack for ( int i=1 ; ; i++ ) { lua_rawgeti(L,-1,i); if ( lua_isnil(L,-1) ) { lua_pop(L,1); break; } /* Do something */ lua_pop(L,1); } 

通过查看源代码,您可以看到这是ipairs内部的工作: http ://www.lua.org/source/5.1/lbaselib.c.html#ipairsaux

 t = {[1]=1, [2]=2, [4]=4} -- has a length of 4 

那么你的问题就在那里; 没有长度为4.你可能认为它确实如此,而#t可能会返回4.但就Lua API而言,该表的长度是未定义的

Lua 5.1声明 :

表t的长度被定义为任何整数索引n,使得t [n]不是nil而t [n + 1]是nil; 此外,如果t 1为零,则n可以为零。 对于常规数组,非n值从1到给定n,其长度恰好是n,即其最后一个值的索引。 如果数组具有“空洞”(即,其他非零值之间的空值),那么#t可以是直接在nil值之前的任何索引(也就是说,它可以将任何这样的nil值视为结束的数组)。

Lua 5.2更加明确 :

只有当表是一个序列时才定义表t的长度,也就是说,对于某个整数n,其正数字键的集合等于{1..n}。 在这种情况下,n是它的长度。 注意表格就好

  {10, 20, nil, 40} 

不是序列,因为它有键4但没有键3.(因此,没有n使得集合{1..n}等于该表的正数字键集。)但请注意,非数字键不会干扰表是否为序列。

但在这两种情况下,长度都是不确定的