[TOC]
使用层次
pairs
遍历table
local tbTestPairs ={
[1] = 1,
nTest_1 = 2,
szTest = "test",
tbTest = {},
nTest_2,
}
for k, v in pairs(tbTestPairs) do
print (k, v)
end
结果
szTest test
tbTest table: 000000000033a630
nTest_1 2
ipairs
按顺序便利table
local tbTestIpairs = {1, 3, 5, nil, 7}
for k, v in ipairs(tbTestIpairs) do
print(k ,v)
end
结果
1 1
2 3
3 5
总结
- pairs是无序的,ipairs是有序的。这点很重要,如果要按存储顺序处理表中内容的时候,pairs就可能得不到预期的结果;
- ipairs遇到nil就停止打印,所以只打印出来前面三个,7没有打印出来
- pairs中为值nil的元素,即使你定义了key是有效的,也是遍历不出来的。所以要小心对key有要求的应用!
- 从上面的结果可以看到tbTestPairs中nTest_2没有打印,这不是因为nTest_2这个key对应的值为nil,而是没有定义key的元素在table里面从前往后依次从[1][2]…开始作为key的,所以nTest_2的key为[1],也覆盖了[1]=1,因此[1]=1也没有打印出来
- 存储结构上pairs对应的是hash表,ipairs对应的是数组。这个很多帖子都有说明,看代码也更明白
理解层次
学习和理解
说到底,pairs和ipairs都是lua中的迭代器。迭代器是一种可以遍历一种结合中所有元素的机制[1]。可以看泛型for的语义:
for <var-list> in <exp-list> do
<body>
end
for在循环过程中保存了迭代器函数。for做的第一件事就是对in后面的表达式求值,这些表达式应该返回3个值供for保存(这里也就知道如果自己实现迭代器需要根据语法要求来写):
- 迭代器函数
- 恒定状态
- 控制变量
在初始化完成之后,for会以恒定状态和控制变量来调用迭代器函数。可以看下面的代码,更加清晰:
for var_1, ..., var_n in <explist> do
<block>
end
-- 等价于以下代码
do
local _f, _s, _var = <explist> -- 返回迭代器函数、恒定状态和控制变量的初值
while true do
local var_1, ..., var_n = _f(_s, _var)
_var = var_1
if _var == nil then
break
end
<block>
end
end
参考[1]中专门对这个泛型for问题说的非常详细!感谢作者^_^
学以致用
- pairs
local function iter(a, k)
k, v = next(a, k);
if v then
return k, v;
end
end
function pairs(t)
return iter, t, nil;
end
- iparis
local function iter(a, i)
i = i + 1;
if a[i] then
return i, a[i];
end
end
function ipairs(t)
return iter, t, 0;
end