在 Lua 中,数组和 nil 是一个复杂的话题。
当你使用 table.pack 时,它会计算参数的数量并将表的 n 值设置为该数量。但如果你使用如 {1, nil, 3, nil} 这样的表构造器,就不是这种情况了。
然而,# 运算符做的又是稍微不同的一件事。
根据手册:
对于一个表,长度操作符返回的是一个表的一个边界。一个边界指的是任意一个在表
t中,自然数索引为一个非nil的值,其后跟随一个nil值(或者自然数索引为 1 且它为nil)的自然数索引。
这意味着,对于表
t = {1, nil, 3, nil}
它可以返回一个 1,因为 t[1] 是 1 且 t[2] 是 nil,或是一个 3,因为 t[3] 是 3 且 t[4] 是 nil。
而 ipairs() 函数则又是做了完全不同的事情:它实际上从 1 开始计算索引,直到在表中遇到一个 nil,因此它总是统计到表中的第一个 _边界_。
如果你想让 # 运算符返回表的 n 值,在 Lua5.2 或更新的版本中,你可以这样做:
local t = {n=10}
setmetatable(t, {__len=function(self) return self.n end})
print(#t) -- 将输出 10,即使 t 没有 0 的数字索引
需要注意的是,在基于 Lua 5.1 的 LuaJIT 中,这种方法是无效的。
同样地,你也可以设置一个表 t 的 __ipairs 元表方法,这样 ipairs(t) 就会从 1 开始计数,直到表的 n 值而不是第一个 nil 元素。
编辑:为什么 ipairs 对你的示例没有起到任何作用呢,这主要是由于我已经解释的其关于 ipairs 的特性,另外,由于表中的第一个键是 nil,它会马上假定表为空,因此什么也不做。
尽管这不是很相关,因为你不应该依赖这种特定实现的行为,但是下面是 PUC Lua 5.3 对表的 # 运算符的实现方法:
/*
** 尝试在表 't' 中找到一个边界。一个“边界”指的是一个整数索引,其为非 nil 值,而后一项为 nil 值 (如果 t[1] 是 nil 则为0)。
*/
lua_Unsigned luaH_getn (Table *t) {
unsigned int j = t->sizearray;
if (j > 0 && ttisnil(&t->array[j - 1])) {
/* there is a boundary in the array part: (binary) search for it */
unsigned int i = 0;
while (j - i > 1) {
unsigned int m = (i+j)/2;
if (ttisnil(&t->array[m - 1])) j = m;
else i = m;
}
return i;
}
/* else must find a boundary in hash part */
else if (isdummy(t)) /* hash part is empty? */
return j; /* that is easy... */
else return unbound_search(t, j);
}
你可以看到,Lua 使用二分搜索来找到边界,这只有在你假定只有一个边界时才有意义;否则,它可能会随机跳过第一个,但突然间在表中添加一个值时就能找到它。
另外需要注意的是,表的数组部分不会每次添加一个值就增加大小。如果我没记错的话,它是每次总是翻倍的;所以你可以有一个四个元素的表,添加一个元素,Lua 会将数组大小增加到 8,再添加另外 4 个元素,它就会增加到 16,尽管表中只有 9 个元素。这是为了避免不必要的内存分配。
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

我问了一个类似的问题
总结一下:由于Lua不支持在表中存储nil值,它将计算直到非nil元素之一。你需要使用ipairs手动计数。这里是参考文献。