Lua Table 间隙避免
Lua Table Gap aviod
为什么 lua table(重新散列?)在我使用不同语法时避免出现空白?
d = require "core/modules/inspect"
案例 1:标准语法第一个元素是一个间隙
t = {1,2,3}
t[1] = nil
d(t)
__________
{ nil, 2, 3 }
Case2:带括号的语法没有空隙
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 没有定义非顺序索引的长度运算符的行为,但是 Why does Lua's length (#) operator return unexpected values? 的公认答案进入了 Lua 5.2 的标准实现中实际发生的情况.也就是说,这个答案本身并不能完全解释行为,所以这里有一个个案解释,使用 Lua 5.3.5 的标准实现。
注意:我使用长度运算符来清楚地显示出现漏洞的情况。关于这如何适用于您使用的检查功能,从我所看到的它的行为来看,它只是明确地声明了范围之外的任何索引 1 <= index <= #table.
案例一:
> t = {1,2,3}
> t[1] = nil
> print(#t)
3
Lua table 的数组部分的大小基于 2 的幂 - 除了 当 table 是用预设值构建。 t = {1,2,3}
行创建了一个 table,其数组部分的大小为 3。当您执行 t[1] = nil
时,数组部分没有理由重新调整大小,因此其大小保持为 3。数组部分的最后一项非零,哈希部分为空,返回数组大小 - 3。
案例二:
> t = {[1] = 1, [2] = 2, [3] = 3}
> t[2] = nil
> print(#t)
1
如果您在 table 构造函数中定义 table 值,Lua 会将方括号内的任何键与 table 的散列部分相关联。所以,table 的数组部分实际上是空的。该实现对数组的散列部分进行二分查找,得到 1.
案例三:
> t = {}
> t[1] = 1
> t[2] = 2
> t[3] = 3
> t[2] = nil
> print(#t)
1
当在构造函数外部使用方括号时,Lua 将检查数字索引以查看它们是否应该进入数组部分或散列部分。在这种情况下,每个索引都将进入数组部分,但因为这些值是在构造函数之外定义的,所以数组的大小将根据 2 的幂进行赋值。因此,在最初的三个赋值之后,数组部分的大小将为 4。nil 赋值不会触发重新调整大小,因此它保持为 4。因此,当应用长度运算符时,它会看到最终值数组中的 space 是 nil,因此它二进制搜索第一个 nil 值之前的索引,即 1.
案例四:
> t = {}
> t[1] = 1
> t[2] = 2
> t[3] = 3
> t[1] = nil
> print(#t)
3
这种情况与情况 3 完全相同,但是二分搜索发现 t[2]
是非零的,因此不考虑 2 之前任何索引处的值。这导致搜索继续在 2 之后的索引上,得出长度为 3.
案例五:
> t = {[1] = 1, [2] = 2, [3] = 3}
> t[1] = nil
> print(#t)
0
从 table 项目是 table 的散列部分的成员的意义上说,这类似于案例 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 决定是将数字索引放在数组部分还是散列部分。上面tablet
的组合中,索引1在数组部分,索引4在哈希部分。因此,返回的长度为 1。在 g
的情况下,所有值都放入数组部分。这是因为在为索引赋值时,Lua 尝试以最佳方式重新调整数组部分的大小。为了更好地了解这个重新调整大小的过程,您可以查看来源 here.
为什么 lua table(重新散列?)在我使用不同语法时避免出现空白?
d = require "core/modules/inspect"
案例 1:标准语法第一个元素是一个间隙
t = {1,2,3}
t[1] = nil
d(t)
__________
{ nil, 2, 3 }
Case2:带括号的语法没有空隙
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 没有定义非顺序索引的长度运算符的行为,但是 Why does Lua's length (#) operator return unexpected values? 的公认答案进入了 Lua 5.2 的标准实现中实际发生的情况.也就是说,这个答案本身并不能完全解释行为,所以这里有一个个案解释,使用 Lua 5.3.5 的标准实现。
注意:我使用长度运算符来清楚地显示出现漏洞的情况。关于这如何适用于您使用的检查功能,从我所看到的它的行为来看,它只是明确地声明了范围之外的任何索引 1 <= index <= #table.
案例一:
> t = {1,2,3}
> t[1] = nil
> print(#t)
3
Lua table 的数组部分的大小基于 2 的幂 - 除了 当 table 是用预设值构建。 t = {1,2,3}
行创建了一个 table,其数组部分的大小为 3。当您执行 t[1] = nil
时,数组部分没有理由重新调整大小,因此其大小保持为 3。数组部分的最后一项非零,哈希部分为空,返回数组大小 - 3。
案例二:
> t = {[1] = 1, [2] = 2, [3] = 3}
> t[2] = nil
> print(#t)
1
如果您在 table 构造函数中定义 table 值,Lua 会将方括号内的任何键与 table 的散列部分相关联。所以,table 的数组部分实际上是空的。该实现对数组的散列部分进行二分查找,得到 1.
案例三:
> t = {}
> t[1] = 1
> t[2] = 2
> t[3] = 3
> t[2] = nil
> print(#t)
1
当在构造函数外部使用方括号时,Lua 将检查数字索引以查看它们是否应该进入数组部分或散列部分。在这种情况下,每个索引都将进入数组部分,但因为这些值是在构造函数之外定义的,所以数组的大小将根据 2 的幂进行赋值。因此,在最初的三个赋值之后,数组部分的大小将为 4。nil 赋值不会触发重新调整大小,因此它保持为 4。因此,当应用长度运算符时,它会看到最终值数组中的 space 是 nil,因此它二进制搜索第一个 nil 值之前的索引,即 1.
案例四:
> t = {}
> t[1] = 1
> t[2] = 2
> t[3] = 3
> t[1] = nil
> print(#t)
3
这种情况与情况 3 完全相同,但是二分搜索发现 t[2]
是非零的,因此不考虑 2 之前任何索引处的值。这导致搜索继续在 2 之后的索引上,得出长度为 3.
案例五:
> t = {[1] = 1, [2] = 2, [3] = 3}
> t[1] = nil
> print(#t)
0
从 table 项目是 table 的散列部分的成员的意义上说,这类似于案例 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 决定是将数字索引放在数组部分还是散列部分。上面tablet
的组合中,索引1在数组部分,索引4在哈希部分。因此,返回的长度为 1。在 g
的情况下,所有值都放入数组部分。这是因为在为索引赋值时,Lua 尝试以最佳方式重新调整数组部分的大小。为了更好地了解这个重新调整大小的过程,您可以查看来源 here.