Lua:ipairs/pairs
Lua中有两个很类似的函数:ipairs以及pairs。
实验环境:
[test1280@localhost 20170531]$ uname -a
Linux localhost.localdomain 2.6.18-371.el5 #1 SMP Thu Sep 5 21:21:44 EDT 2013 x86_64 x86_64 x86_64 GNU/Linux
[test1280@localhost 20170531]$ lua -v
Lua 5.3.4 Copyright (C) 1994-2017 Lua.org, PUC-Rio
pairs(t)
sample 1:
test.lua:
t = {"a", "b", "c", "d", "e", "f"}
for k, v in ipairs(t) do
print("key is " .. k)
print("value is " .. v)
end
[test1280@localhost 20170531]$ lua test.lua
key is 1
value is a
key is 2
value is b
key is 3
value is c
key is 4
value is d
key is 5
value is e
key is 6
value is f
上面的输出可以证明:
1.在Lua中ipairs是从下标1开始的,并不是从0开始;
2.就如同我们例子中的变量名,k以及v,就是key以及value,每次都会返回两个值赋给k以及v,然后可以在loop-body部分使用。
sample 2:
test.lua:
t = {
"a", "b", "c";
one = "d", two = "e", three = "f";
}
for k, v in ipairs(t) do
print("key is " .. k)
print("value is " .. v)
end
[test1280@localhost 20170531]$ lua test.lua
key is 1
value is a
key is 2
value is b
key is 3
value is c
前三个还是正常迭代的,第四个出问题了。
因为ipairs总是从1开始进行迭代:
如果t[n]的值不是nil,那么就可以进入循环==》
if (t[1] ~= nil) then
do loop-body
if (t[2] ~= nil) then
do loop-body
if (t[3] ~= nil) then
do loop-body
...
当发现t[n]值是nil时则直接退出循环。
思考下面的代码输出什么:
sample 3:
test.lua:
t = {
zero = "this is zero",
"a", "b", "c";
one = "d", two = "e", three = "f";
}
for k, v in ipairs(t) do
print("key is " .. k)
print("value is " .. v)
end
[test1280@localhost 20170531]$ lua test.lua
key is 1
value is a
key is 2
value is b
key is 3
value is c
千万不要以为将一个key-value放置在table靠前处就可以阻挡ipairs…
记住,无论table是啥,ipairs总是尝试从1开始索引,判断是否是nil,不是nil则进入loop-body,是nil则退出,依次类推。
sample 4:
test.lua:
t = {
zero = "this is zero",
one = "d", two = "e", three = "f";
}
t[1] = "a"
t[2] = "b"
t[3] = "c"
for k, v in ipairs(t) do
print("key is " .. k)
print("value is " .. v)
end
其实这里的修改是与sample 3等价的,输出如下:
[test1280@localhost 20170531]$ lua test.lua
key is 1
value is a
key is 2
value is b
key is 3
value is c
假若:
sample 5:
test.lua:
t = {
zero = "this is zero",
one = "d", two = "e", three = "f";
}
t[1] = nil
t[2] = "b"
t[3] = "c"
for k, v in ipairs(t) do
print("key is " .. k)
print("value is " .. v)
end
输出将会是什么?
Answer is:啥也不输出。
sample 6:
test.lua:
t = {
zero = "this is zero",
one = "d", two = "e", three = "f";
}
t[1] = "a"
t[2] = nil
t[3] = "c"
for k, v in ipairs(t) do
print("key is " .. k)
print("value is " .. v)
end
输出是啥?
[test1280@localhost 20170531]$ lua test.lua
key is 1
value is a
回想我们刚刚的过程:
先判断t[1]是不是nil,发现不是,那么就进入loop-body;
在判断t[2]是不是nil,发现是,那么就退出…
由以上的ipairs引出一个问题,如何迭代一个既有数组类型,又有记录风格(就是key-value风格)的table呢?
下面就轮到pairs出场了。
pairs(t)
sample 7:
test.lua:
t = {
zero = "this is zero",
one = "d", two = "e", three = "f";
}
t[1] = "a"
t[2] = nil
t[3] = "c"
for k, v in pairs(t) do
print("key is " .. k)
print("value is " .. v)
end
[test1280@localhost 20170531]$ lua test.lua
key is 1
value is a
key is one
value is d
key is 3
value is c
key is three
value is f
key is two
value is e
key is zero
value is this is zero
sample 7对比sample 6只是将ipairs改成了pairs,结果却大不相同。
从输出中看到一下三点:
pairs可以遍历tabe中所有的元素,无论是key-value或者是数组类型;
pairs对元素(key)的遍历是无序的,这一点需要注意,因为这里的遍历是与key的哈希值有关,有机会我再看看源码^_^;
pairs没有对t[2]输出key is 2,为什么呢?因为在Lua中,一个值是nil,本身代表这个值压根没有定义过…
总结:
ipairs和pairs都可以对table进行遍历,但是:
ipairs总是对数组类型按序进行遍历,但也仅仅对数组类型的元素遍历了,而对key-value类型不闻不问;
pairs相对ipairs可以对所有的table元素进行遍历,包括key-value类型,但是其遍历不是按照某些特定的顺序(比如key字典顺序等等),而是与key的Hash值有关,表现出来的就是无序的遍历,这一点需要注意。
Tips:
对ipairs以及pairs可以认为,加了“i”的是对数组进行遍历,整数么,哈哈。
特别需要注意的是,在迭代时对table的修改会不会影响迭代本身呢?(参见lua_next)==》