tNum={[2]=true , [3]=true,[4]=true, [5]=true ,[6]=true }
#tNum-->0
tNum={}
tNum[2]=true
tNum[3]=true
tNum[4]=true
tNum[5]=true
tNum[6]=true
#tNum-->6
为什么尺寸如此不同? 两个例子都一样吗?
答案 0 :(得分:2)
问题在于,当您将表定义为从索引[2]
开始时,长度运算符会中断,因为它假定表从索引[1]
开始。
下面的代码按预期工作:
tNum = {[1]=false, [2]=true, [3]=true, [4]=true, [5]=true, [6]=true}
#tNum => 6
之所以会出现这种奇怪的行为,是因为当您使用tNum={}
初始化数组时,它会通过将每个索引分配给nil来初始化,而第一个索引是[1]
(实际上并没有将每个值都初始化为nil ,但这样解释起来更容易)。
相反,当您使用tNum={[2]=true}
初始化数组时,您将明确告诉该数组tNum[1]
不存在,并且该数组从索引2开始。这个。
有关更详尽的解释,请参阅lua Wiki底部的this section,其中解释如下:
对于那些确实希望数组从0开始的人,编写以下内容并不困难:
days = {[0]="Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"}
现在,第一个值“ Sunday”位于索引0。那个零不会影响其他字段,但是“ Monday”自然会进入索引1,因为它是构造函数中的第一个列表值;其他值跟随它。尽管有此功能,但我不建议在Lua中使用从0开始的数组。请记住,大多数函数都假定数组从索引1开始,因此将无法正确处理此类数组。
Length运算符假定您的数组将从索引[1]
开始,由于它不存在,因此无法正常工作。
我希望这对您有所帮助,祝您代码顺利!
答案 1 :(得分:2)
您的两个表在语义上是相同的,但是在它们上使用#
是不明确的。 0和6都是正确的长度。这是an abridged version of the docs:
应用于表的长度运算符在该表中返回 border 。表
t
中的边框是满足以下条件的任何自然数:(border == 0 or t[border] ~= nil) and t[border + 1] == nil
只有一个边界的表称为序列。
当t不是序列时,#t可以返回其任何边界。 (确切的一个取决于表的内部表示的详细信息,而表的内部表示又取决于表的填充方式及其非数字键的内存地址。)
这是未定义行为(UB)的示例。 (这可能不正确,因为行为是部分定义的。Lua中的UB无法像C语言那样发射核武器。)未定义的行为很重要,因为它使开发人员可以自由选择最快的速度算法,而不必担心用户违反假设时会发生什么。
要找到长度,Lua最多只能进行 log n 个猜测,而不是查看每个元素来确定一个明确的长度。对于大型阵列,这可以大大加快速度。