表大小的差异。两个例子都一样吗?

时间:2018-08-05 13:38:09

标签: lua lua-table

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 

为什么尺寸如此不同? 两个例子都一样吗?

2 个答案:

答案 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 个猜测,而不是查看每个元素来确定一个明确的长度。对于大型阵列,这可以大大加快速度。