在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和最后找到的整数键来继续遍历表的其余部分,从而避免再次遍历整数键部分?这样做有两次我会看到一些整数键吗?
答案 0 :(得分:9)
你只需使用rawgeti,直到你得到一个零键:
// 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
答案 1 :(得分:3)
t = {[1]=1, [2]=2, [4]=4} -- has a length of 4
那里有你的问题;没有长度为4.你可能认为确实如此,而#t
可能会返回4.但就Lua API而言,此表的长度为未定义
表t的长度定义为任何整数索引n,使得t [n]不为零且t [n + 1]为零;此外,如果t 1为零,则n可以为零。对于常规数组,非n值从1到给定n,其长度恰好是n,即其最后一个值的索引。如果数组具有“空洞”(即,其他非零值之间的nil值),那么#t可以是直接在nil值之前的任何索引(也就是说,它可以将任何这样的nil值视为结束数组)。
Lua 5.2 is rather more explicit:
表t的长度仅在表是序列时定义,即,对于某个整数n,其正数字键的集合等于{1..n}。在这种情况下,n是它的长度。请注意像
这样的表格
{10, 20, nil, 40}
不是序列,因为它有键4但没有键3.(因此,没有n使得集合{1..n}等于那个正数字键的集合但请注意,非数字键不会干扰表是否为序列。
但在这两种情况下,长度都是未定义。