Lua有#运算符来计算"长度"用作数组的表。 我检查了这个操作员,我感到很惊讶。
这是代码,我让它在Lua 5.2.3下运行:
t = {};
t[0] = 1;
t[1] = 2;
print(#t); -- 1 aha lua counts from one
t[2] = 3;
print(#t); -- 2 tree values, but only two are count
t[4] = 3;
print(#t); -- 4 but 3 is mssing?
t[400] = 400;
t[401] = 401;
print(#t); -- still 4, now I am confused?
t2 = {10, 20, nil, 40}
print(#t2); -- 4 but documentations says this is not a sequence?
有人可以解释规则吗?
答案 0 :(得分:23)
引用Lua 5.2参考手册:
表t的长度仅在表是序列时定义,即,对于某个整数n,其正数字键的集合等于{1..n}
#
运算符对非序列的结果是 undefined 。
但是what happens in C implementation of Lua when we call #
on a non-sequence?
背景:Lua中的表在内部分为数组部分和散列部分。这是一个优化。 Lua试图避免经常分配内存,所以它预先分配下一个2的幂。那是另一个优化。
nil
时,#
的结果是通过bin搜索第一个零跟随键的数组部分找到的最短有效序列的长度。nil
并且散列部分为空时,#
的结果是数组部分的物理长度。nil
并且哈希部分非空时,#
的结果是通过bin搜索哈希部分找到的最短有效序列的长度第一个nil-follow键(即i
和t[i] ~= nil
这样的正整数t[i+1] == nil
,假设数组部分充满了非nils(!)。因此,#
的结果几乎总是最短有效序列的(期望的)长度,除非表示非序列的数组部分中的最后一个元素是非零的。然后,结果是大于。
为什么?这似乎是另一个优化(对于两个幂大小的数组)。此类表格#
的复杂程度为O(1)
,其他变体为O(log(n))
。