Lua表差距

时间:2019-03-05 08:26:16

标签: lua lua-table

当我使用不同的语法时,为什么lua表(重新整理?)可以避免出现间隙?

inspect function

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 }

1 个答案:

答案 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