在Lua, pairs
和 ipairs
可以以不同的顺序迭代相同的元素:
> 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
您只需使用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;而且,如果t1 是零,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}等于该表的正数字键集。)但请注意,非数字键不会干扰表是否为序列。
但在这两种情况下,长度都是 未定义。