Lua内容关于for循环的总结(一)

转载注明出处即可。无需经过本人同意。

本文章声明如下:此内容为网上内容的总结以及本人的总结。如存在侵权,请通知本人删除文章。

通过学习Lua后,你可能会碰到很多种for的循环,其中的差异你是否了解呢?本篇文章将介绍本人目前所认识到的所有for有关内容。你将会了解如下内容:

  • for循环的分类:数值遍历以及泛型遍历

  • pairs以及ipairs的区别(这部分内容将会出现在for循环的分类中出现)

  • 泛型遍历的分类:无状态迭代器以及多状态迭代器(现在看不懂没关系,可以先放着,往后看)

for循环的分类

for循环的分类可以分为数值遍历以及泛型遍历。
数值遍历是根据表的长度进行遍历,而泛型遍历是通过迭代器遍历。下面分别进行阐述。

数值遍历

如下所示:

tbtest={12,3,12,2312}

--第一种
for i=1, #(tbtest) do  
    print(tbtest[i])
end 

--第二种
for i=1, table.maxn(tbtest) do  
    print(tbtest[i]) 
end 

第一种

第一种是使用 ‘#’,这个符号的作用是是获取table的长度,比如:

tbtest = {  
    [1] = 1,  
    [2] = 2,  
    [6] = 6, 
    ["3"] = 5 
}  
--输出的结果为2,后面解释。
print(#(tbtest)) 

#可以获得表的长度。但是要求表的key是数值且从1开始递增的(这里的递增是指在上一个值的基础上加1)。

从上面的解释就知道了,为什么上面的例子输出的是2。键[“3”]是字符串,而不是数值,所以不能算。而[6]与之前的两个键不是递增的关系,所以也不能算。故此上面的结果为2。

知道了#的使用规则,可以试着修改上面的例子。
例如将key=[1]的键值对删除,结果就为0,因为键key没有从1开始递增。
还有一点需要注意的,#只要求key是递增的,而没有要求key是按照递增的顺序排列。如将上面的代码修改为如下:

tbtest = {  
    [1] = 1,  
    [3] = 6,
    [4]=  7,
    [2] = 2,  
}  
--输出的结果为4print(#(tbtest)) 

注意上面的key排列顺序,tbtest[3],tbtest[4]的位置放在tbtest[2]的前面,虽然它们的排列顺序没有按照从1递增的顺序排列,但是它们的key是从1开始递增的,也就是说使用 # 对排列顺序没有要求

—————————————————————-
题外话:
1 . 在这里提一下# 的另一个用法:#还可以获得字符串的长度,如下所示:

name="asd"
print(#name)

2 . table.getn(table)
–等同于操作符 #
作用:得到一个table的大小。
注意:该table的key必须是有序的,索引是从1开始的。

tbtest = {  
    [1] = 1,  
    [3] = 6,
    [4]=  7,
    [2] = 2,      
}  
--输出4
print(table.getn(tbtest))

—————————————————————-

总结:

for i=1, #(tbtest) do这种遍历,只能遍历当tbtest中存在key为1的value时才会出现结果,而且是按照key从1开始依次递增1的顺序来遍历,找到一个递增不是1的时候就结束不再遍历,无论后面是否仍然是顺序的key。

key也要求是数值,而不能是字符串数字。即要求是[1]=10,而不能是[“1”] =10。


第二种

第二种是使用table.maxn()。

table.maxn获取的只针对整数的key字符串的数字key是没办法获取到的。获取的是key值中最大的值
和table内的定义顺序没有关系,无论你是否先定义的key为6的值,table.maxn都会获取整数型key中的最大值
此种遍历效率极低,因为如果你整数key中定义的最大的key是10000,然而10000以下的key没有几个,那么这么遍历会浪费很多时间,因为会从1开始直到10000 每一个元素都会查找一遍,实际上大多数元素都是不存在的。比如:

tbtest = {  
    [1] = 1,  
    [10000] = 2,  
}  
--请自行测试,结果就不展示了
for i=1, table.maxn(tbtest) do  
    print(tbtest[i])  
end  

此外如果table是:

tbtest = {  
    ["a"] = 1,  
    ["b"] = 2,  
    ["c"] = 3,  
}  
--那么打印的就全部是0了。
print(table.maxn(tbtest))  
print(#(tbtest)) 

因为table.maxn(),# 都要求key为数值,而不是字符串,即使是数字字符串也不行(即[“1”]=10)


泛型遍历

如下所示:

tbtest={12,23,211,23}

--第三种
for key, value in pairs(tbtest) do  
    print(key,value)  
end 

--第四种 
for key, value in ipairs(tbtest) do  
    print(key,value)  
end 

泛型遍历就是使用迭代器来遍历,例如pairs、ipairs,也可以使用自己定义的迭代器(稍后再介绍)。

首先要明确一点,就是lua中table并不是像是C/C++中的数组一样是顺序存储的,准确来说lua中的table更加像是C++中的map,通过Key对应存储Value,但是并非顺序来保存key-value对,而是使用了hash的方式,这样能够更加快速的访问key对应的value。
我们也知道hash表的遍历需要使用所谓的迭代器来进行,同样,lua也有自己的迭代器,也就是paris以及ipairs。


第三种

for k,v in pairs(tbtest) do 这样的遍历顺序并非是tbtest中table的排列顺序,而是根据tbtest中key的hash值排列的顺序来遍历的。
如下代码:

tbtest = {  
    [1] = 1,  
    [2] = 2,  
    [3] = 3,  
    [4] = 4,  
} 

for key, value in pairs(tbtest) do  
    print(value)  
end 
--输出结果为: 
--[[
1
2
4
3
]]

从上面可以看到,tbtest[4]的结果在tbtest[3]的上面。也就是说使用pairs()并不是按照key的排列顺序来输出的,而是按照key的hash值排列顺序来遍历


第四种

lua也提供了按照key的大小顺序来遍历的,注意,是大小顺序,仍然不是key定义的顺序,这种遍历方式就是for k,v in ipairs(tbtest) do。
for k,v in ipairs(tbtest) do 这样的循环必须要求tbtest中的key为顺序的,而且必须是从1开始,ipairs只会从1开始按连续的key顺序遍历到key不连续为止。 注意是从1开始的。
(注意是值为顺序的,而不要求定义时也是顺序的。参考如下示例)

--[[
ipairs只能遍历key为数字的,而不能遍历字符串数字。
即key值可以为[3],而不能为["3"]。
而且只能从key为1开始遍历,然后在key中寻找按1递增的key。
这些不需要按照顺序排列,如下所示。
]]

t={"a",12,[5]=12,[4]=22,[3]="c"}  
for k,v in ipairs(t) do
   print(k,v)
end

--[[输出结果如下:
1   a
2   12
3   c
4   22
5   12
]]

从上面的例子可以看出,只要求key是从1开始递增的,而不要求在排列的顺序上也是按照递增的顺序排列。


总结:

  1. pairs(): 按照key的Hash值顺序进行遍历。
  2. ipairs(): 按照key的大小顺序(不是定义顺序),必须是从key为1开始,顺序遍历到key不连续为止。
  3. #(tab): 按照key从1开始依次递增1的顺序来遍历,找到一个递增不是1的时候就结束不再遍历(同ipairs差不多)。
  4. table.maxn(tab): 获取key中的最大值。
  5. 除了pairs,其他的三个都要求整数的key,字符串的key是无法获取的。即要求是[3]=10,而不能是[“3”] =10。

由于内容太多,如需要请看下一篇博客《Lua内容关于for循环的总结(二)》

猜你喜欢

转载自blog.csdn.net/qq_28644183/article/details/71601461
今日推荐