这个的文章挺多的,但是有好几种说法并且不全。有人说是忽略手动设定值,有人说是从1开始数,直到序号断开,还有人给出结果,但是和我实机测试的效果不一样, 所以我自己总结一篇。
经过我的测试和总结得到以下结论:
ipairs是一个专用的遍历函数,主要用于遍历数组,即索引为正整数的表。可以用于遍历表中的所有键值对,其中键仅限于正整数。ipairs遍历和手动设置序号的先后位置无关,优先从非手动设定位置从左向右开始计算非手动设置的索引,计算非手动设置的索引时会跳过手动设定的索引,计算完非手动设定的索引后,寻找手动设定索引,如果手动设定的序号能连上,则算上手动设置的索引连续打印,直到序号断开。
根据以上结论尝试推断以下表输出:
a={[5]="hello",[3]=2,3,4}
for i, v in ipairs(a) do
print(i, v)
end
从非手动设定位置优先开始从左向右计算索引,则为[1]=3,[2]=4,之后寻找手动设定序号,[3]=2。之后继续寻找,只找到5,数字连续性断开,所以只能打印到3的索引。推测结果为[1]=3,[2]=4,[3]=2
和实际结果相符。
以下为推论部分
接下来我们将通过几个实例来推导出具体的原理
例子一
a={[1]="hello",2,[2]=3,4,5}
for i, v in ipairs(a) do
print(i, v)
end
结果如下。
手动设定的[1]和[2]并没有打印出来,所以猜测lua会忽略手动设定值,从2开始计算索引,2索引为1,4索引为2,5索引为3,
例子二
a={[1]="hello",[2]=2,[3]=3}
for i, v in ipairs(a) do
print(i, v)
end
例子一中是忽略手动设定的key值,但是例子二中全部手动设定,得到结果却是全部输出。
因此我认为,lua并不会忽略手动设定的整数值索引,猜测如果全部手动设定且为连续正整数则可以识别,如果其中有不是手动设定的则优先非手动设置的开始计算索引
例子三
a={[1]="hello",[2]=2,3}
for i, v in ipairs(a) do
print(i, v)
end
如图,根据以上推断,优先计算3的索引为1,此时3明明在后面,但结果却是3,2。说明3索引为1,2索引为2,hello的索引断开。这个例子说明序号可以倒序相连。
猜测ipairs是全部元素遍历完后,再寻找连续序号输出,直到序号断开,
例子四
a={[3]="hello",[2]=2,3}
for i, v in ipairs(a) do
print(i, v)
end
倒序输出了3,2,"Hello"。因此可以推断以上假设为真。
因此得出重要结论:ipairs遍历和序号先后位置无关,从非手动设定位置优先从左向右开始计算索引,非手动设定位置索引计算完成后,寻找手动设定索引,如果序号能连上,则算上手动设置的索引连续打印,直到序号断开。
例子五
根据以上推断尝试推断以下表输出:
a={[5]="hello",[3]=2,3,4}
for i, v in ipairs(a) do
print(i, v)
end
从非手动设定位置优先开始从左向右计算索引,则为[1]=3,[2]=4,之后寻找手动设定序号,[3]=2。之后继续寻找,只找到5,数字连续型断开,所以只能打印到3的索引。推测结果为[1]=3,[2]=4,[3]=2
和实际结果相符。
同时根据此结论可以知道例子一a={[1]="hello",2,[2]=3,4,5}的输出为何忽略了[1]=1和[2]=3,因为2,4,5分别占用了1,2,3的索引,接下来要寻找的索引应该是4了,所以忽略掉了[1]和[2],此时若把[1]="Hello"和[2]=3改为[4]="hello",[5]=3则可以打印出2,4,5,"hello",3。
a={[4]="hello",2,[5]=3,4,5}
for i, v in ipairs(a) do
print(i, v)
end
和实际结果相符。
例子七
非手动索引时如何计算的?只计算连续的默认索引还是会跨过手动设置的索引?
a={[2]=0,[4]=0,1,2,3,[5]=6,7,8,9}
for i, v in ipairs(a) do
print(i, v)
end
如果是分块连续索引,则应该是1,2,3后寻找手动索引,得到[4]=0,[5]=6,即1,2,3,0,6
如果是跳过非手动设置索引,则应是,1,2,3,7,8,9
实际结果如下,因此是跳过手动设置的索引进行计算的。