Lua中pairs与ipairs的区别总结
前言
最近在用nginx_lua_module模块写一个流量转发的东西,根据Header,Body,Cookie按照流量比例转发到另一个地方。看了前人写的代码,里面循环的时候有的用pairs,有的用ipairs,很不解。好在Lua官网就有电子版的《ProgramminginLua》,学习非常方便。以下内容是我初学Lua的笔记和思考,如果不正确,欢迎指正。
标准库提供了集中迭代器,包括迭代文件每行的(io.lines),迭代table元素的(pairs),迭代数组元素的(ipairs),迭代字符串中单词的(string.gmatch)等等
pairs与ipairs区别
一般的迭代器是在内部维护一个状态的(当前迭代的位置),但是Lua的迭代器是Stateless(无状态的),这样的好处是可以重复多次迭代。不像Python的Iterator和Iterable,如果多次迭代的话,需要从Iterable获得一个迭代器Iterator。Lua的迭代器需要循环的时候自己维护。
每一次迭代,for都会调用迭代器函数,传入的参数有2个,一个是无状态的、要迭代的对象,一个就是控制参数(迭代的状态,123…)。
比如下面这个循环:
a={"one","two","three"} fori,vinipairs(a)do print(i,v) end
首先ipairs(a)执行,返回三个值:iter函数(从这里看出Lua和Python一样是有“一等函数”的),迭代的对象a,和迭代开始的下标0。然后第一次for循环调用iter(a,0)(参数如我们上面所说),得到返回值当前下标i和a[i]的值v,将这两个值赋值给for循环定义时候的变量i和v。用Lua实现这个逻辑,如下:
functioniter(a,i) i=i+1 localv=a[i] ifvthen returni,v end end functionipairs(a) returniter,a,0 end
那么上面的for循环调用的逻辑类似下面这样,首先调用ipairs函数得到iter函数,然后每次调用iter函数。
iter_function,stateless,index=ipairs(a) iter_function(stateless,index) 1one iter_function(stateless,index+1) 2two iter_function(stateless,index+2) 3three
另外一个要注意的点是,上面的Lua代码判断了v,如果不为nil才继续。而实际的for循环中也是这样的。比如我们下面这个循环,因为第二个值是nil,所以打印只会出现第一个元素。
a={"one",nil,"three"} fori,kinipairs(a)do print(i,k) end 1one
然后我们在来说说pairs。其实从上面的描述中也可以发现,ipars是从1开始取值到nil截止,那么如果table中如果有nil但是又想取出所有的元素,就很不方便了。这个时候就可以用pairs。
functionpairs(t) returnnext,t,nil end
for循环的逻辑在上面已经说了,pairs在这里的不同是,它返回的三个元素是next函数,迭代的对象a,开始的状态nil。可以看到不同点主要有两个:第一个是函数next,它和iter的不同是,它返回的是下一个keyvalue,并且顺序固定,直到没有任何keyvalue对了,迭代结束。
我们可以通过几个例子看它们的区别。
a={"one","two","three"} fori,vinipairs(a)do print(i,v) end fori,vinpairs(a)do print(i,v) end
打印值如下:
1 one
2 two
3 three
1 one
2 two
3 three
两个结果一样,因为在这个table中key都是123,所以pair用iter循环(下标从1开始到第一个不是nil的值),还是ipairs用next循环(下标从nil开始遍历所有的keyvalue),效果都是一样的。
t={ a="apple", b="baby", c="cool" } fori,vinipairs(t)do print(i,v) end fork,vinpairs(t)do print(k,v) end
结果是pairs可以打印出来结果,ipairs打印的结果为空。因为t[1]的值是nil,所以ipairs循环刚开始就停止了。
再来看最后一组例子(从参考资料1抄来的):
ocalt={ a=100,10,20,[5]=30 } forkey,valueinipairs(t)do print(key,value) --110 --220 end forkey,valueinpairs(t)do print(key,value) --110 --220 --a100 --530 end
结果如注释中所示,就不必解释了吧。
了解了它们的区别,用起来就非常简单了。ipairs一般用于需要下标、迭代array形式的table;pairs可以用来迭代字典形式的table。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。
参考资料:
- table使用手册
- 《Programminginlua》