Lua表间隙aviod

Lua表间隙aviod,lua,lua-table,Lua,Lua Table,当我使用不同的语法时,为什么lua表(重新创建?)可以避免空白 案例1:标准语法第一个元素是间隙 t = {1,2,3} t[1] = nil d(t) __________ { nil, 2, 3 } 案例2:带括号的语法没有间隙 t = { [1] = 1, [2] = 2, [3] = 3, } t[2] = nil d(t) __________ { 1, [3] = 3 } 案例3:动态阵列-无间隙 t = {} t[1] = 1 t[2] = 2

当我使用不同的语法时,为什么lua表(重新创建?)可以避免空白

案例1:标准语法第一个元素是间隙

t = {1,2,3}
t[1] = nil
d(t)
__________
{ nil, 2, 3 }
案例2:带括号的语法没有间隙

 t = {
    [1] = 1,
    [2] = 2,
    [3] = 3,
}
t[2] = nil
d(t)
__________
{ 1,
  [3] = 3
}
案例3:动态阵列-无间隙

t = {}
t[1] = 1
t[2] = 2
t[3] = 3
t[2] = nil
d(t)
__________
{ 1,
  [3] = 3
}
案例4:在第一个元素中设置为nil时的动态数组-是一个间隙

t = {}
t[1] = 1
t[2] = 2
t[3] = 3
t[1] = nil
d(t)
__________
{ nil, 2, 3 }
案例5:第一个元素中的括号语法设置为nil仍然没有间隙

t = {
    [1] = 1,
    [2] = 2,
    [3] = 3,
}
t[1] = nil
d(t)
__________
{
  [2] = 2,
  [3] = 3
}

Lua没有为非顺序索引定义长度运算符的行为,但公认的答案是Lua5.2的标准实现中实际发生的情况。也就是说,这个答案本身并不能完全解释这种行为,所以这里使用Lua5.3.5的标准实现来逐案解释

注意:我使用“长度”操作符来清楚地显示出现孔的情况。关于这如何应用于您所使用的检查函数,从我对其行为的了解来看,它只是显式地声明了范围1t[1]=nil之外的任何索引 >打印(#t) 3. Lua表的数组部分的大小基于二的幂-除非表是用预设值构造的。行
t={1,2,3}
创建了一个包含大小为3的数组部分的表。执行
t[1]=nil
时,阵列部件没有理由重新调整大小,因此其大小保持在3。由于数组部分的最后一项为非nil,而散列部分为空,因此返回数组大小-3

案例2:

> t = {}
> t[1] = 1
> t[4] = 4
> print(#t)
1
> g = {}
> g[1] = 1
> g[3] = 3
> g[4] = 4
> print(#g)
4
>t={[1]=1,[2]=2,[3]=3}
>t[2]=nil
>打印(#t)
1.
如果在表构造函数中定义表值,Lua将把方括号内的任何键与表的哈希部分相关联。因此,表的数组部分实际上是空的。该实现对数组的哈希部分执行二进制搜索,得到1

案例3:

> t = {}
> t[1] = 1
> t[4] = 4
> print(#t)
1
> g = {}
> g[1] = 1
> g[3] = 3
> g[4] = 4
> print(#g)
4
>t={}
>t[1]=1
>t[2]=2
>t[3]=3
>t[2]=nil
>打印(#t)
1.
当在构造函数外部使用方括号时,Lua将检查数字索引,看它们是否应该进入数组部分或散列部分。在这种情况下,每个索引都将进入数组部分,但由于这些值是在构造函数之外定义的,因此数组的大小将根据2的幂赋值。因此,在最初的三次赋值之后,数组部分的大小将为4。nil赋值不会触发重新调整大小,因此它保持在4。因此,当应用length运算符时,它会看到数组空间中的最终值为nil,因此它会在第一个nil值(即1)之前对索引进行二进制搜索

案例4:

> t = {}
> t[1] = 1
> t[4] = 4
> print(#t)
1
> g = {}
> g[1] = 1
> g[3] = 3
> g[4] = 4
> print(#g)
4
>t={}
>t[1]=1
>t[2]=2
>t[3]=3
>t[1]=nil
>打印(#t)
3.

这种情况与3的情况完全一样,但是二进制搜索发现<代码> t(2)< /C>不为零,因此在2之前不考虑任何索引的值。这将导致在2之后继续搜索索引,从而得出长度为3的结论

案例5:

> t = {}
> t[1] = 1
> t[4] = 4
> print(#t)
1
> g = {}
> g[1] = 1
> g[3] = 3
> g[4] = 4
> print(#g)
4
>t={[1]=1,[2]=2,[3]=3}
>t[1]=nil
>打印(#t)
0
这与情况2类似,因为表项是表的哈希部分的成员。但是,在本例中,搜索过程的结果为0。这是因为在尝试二进制搜索之前,函数确定应该搜索的整数索引范围。在第一个索引处出现nil值意味着确定范围的循环不运行。有关搜索过程如何工作的更多信息,请参见函数。当我说循环不运行时,我特别指的是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试图以最佳方式重新调整数组部分的大小。为了更好地理解这个重新调整大小的过程,您可以查看源代码。

d()
中有什么?它不是内置的Lua函数。是的,它的自定义函数用于调试数组,我认为它可能只是这个函数的结果-这是该函数的一个特定行为。问问它的作者,如果你不喜欢它。或者最好编写自己的函数。在您看来,将表
{nil,2,3}
显示为数组或字典的正确方法是什么?但是为什么p({nil,nil,2,3,nil,4,nil})-4和p({nil,nil,2,3,nil,4})-6(因为分配的空间最多有一半是空的)?运算符
#
不适用于内部包含nils的数组(#可能返回垃圾而不是长度)。这就是为什么您应该编写自己的函数
d()
,它不依赖于
#
运算符。