当我使用不同的语法时,为什么lua表(重新整理?)可以避免出现间隙?
window.addEventListener('beforeunload', function (e) {
// Cancel the event
e.preventDefault();
// Chrome requires returnValue to be set
e.returnValue = '';
});
案例1:标准语法的第一个元素是空白
d = require "core/modules/inspect"
第2种情况:带有方括号的语法没有空格
t = {1,2,3}
t[1] = nil
d(t)
__________
{ nil, 2, 3 }
第3种情况:动态数组-没有空隙
t = {
[1] = 1,
[2] = 2,
[3] = 3,
}
t[2] = nil
d(t)
__________
{ 1,
[3] = 3
}
案例4:在第一个元素中设置nil时的动态数组-是一个缺口
t = {}
t[1] = 1
t[2] = 2
t[3] = 3
t[2] = nil
d(t)
__________
{ 1,
[3] = 3
}
案例5:在第一个元素中将方括号语法设置为nil仍然没有空格
t = {}
t[1] = 1
t[2] = 2
t[3] = 3
t[1] = nil
d(t)
__________
{ nil, 2, 3 }
答案 0 :(得分:1)
Lua并未为非顺序索引的长度运算符定义行为,但是对Why does Lua's length (#) operator return unexpected values?的可接受答案是在Lua 5.2的标准实现中实际发生的事情。就是说,这个答案本身并不能完全解释其行为,因此,这里是使用Lua 5.3.5的标准实现进行个案解释。
注意:我使用长度运算符来清楚地显示出现孔的情况。关于如何将其应用于您使用的检查功能,从我的行为看,它只是明确声明超出1 <= index <= #table范围的任何索引。
案例1:
> t = {1,2,3}
> t[1] = nil
> print(#t)
3
Lua表的数组部分的大小基于2的幂- except (当使用预设值构造表时)。第t = {1,2,3}
行创建的表的数组部分的大小为3。执行t[1] = nil
时,数组部分没有理由重新调整大小,因此其大小保持为3。数组部分为非nil,哈希部分为空,则返回数组大小-3-。
案例2:
> t = {[1] = 1, [2] = 2, [3] = 3}
> t[2] = nil
> print(#t)
1
如果要在表构造函数中定义表值,Lua会将方括号内的任何键与表的哈希部分相关联。因此,表的数组部分实际上是空的。该实现对数组的哈希部分执行二进制搜索,并得到1。
案例3:
> t = {}
> t[1] = 1
> t[2] = 2
> t[3] = 3
> t[2] = nil
> print(#t)
1
在构造函数之外使用方括号时,Lua将检查数字索引以查看它们是否应放入数组部分或哈希部分。在这种情况下,每个索引都将进入数组部分,但是由于这些值是在构造函数之外定义的,因此数组将根据赋值为2的幂进行大小调整。因此,在最初的三个赋值之后,数组部分的大小将为4。nil赋值不会触发重新调整大小,因此它将保持为4。因此,在应用length运算符时,它将看到最终值在数组空间中的值为nil,因此它在第一个nil值(即1)之前二进制搜索索引。
案例4:
> t = {}
> t[1] = 1
> t[2] = 2
> t[3] = 3
> t[1] = nil
> print(#t)
3
这种情况与情况3完全相同,但是二进制搜索发现t[2]
为非nil,因此不考虑2之前的任何索引的值。这导致搜索继续在2之后索引,得出长度为3。
案例5:
> t = {[1] = 1, [2] = 2, [3] = 3}
> t[1] = nil
> print(#t)
0
从表项是表的哈希部分的成员的意义上来说,这类似于情况2。但是,在这种情况下,搜索过程的结果为0。这是因为在尝试二进制搜索之前,该函数确定应搜索的整数索引范围。在第一个索引处存在nil值意味着确定范围的循环不会运行。有关该搜索过程如何工作的更多信息,您可以查看函数here。当我说循环不运行时,我指的是while条件!ttisnil(luaH_getint(t, j))
。
奖励情况:
> t = {}
> t[1] = 1
> t[4] = 4
> print(#t)
1
> g = {}
> g[1] = 1
> g[3] = 3
> g[4] = 4
> print(#g)
4
在案例3中,我提到Lua决定在数组部分还是在哈希部分中放置数字索引这一事实。在上面的表t
的组成中,索引1在数组部分中,而索引4在哈希部分中。这样,返回的长度为1。在g
的情况下,所有值都放入数组部分。这是因为在为索引分配值时,Lua尝试以最佳方式调整数组部分的大小。为了进一步了解此调整大小过程,您可以查看源here。