Pairs and IPairs on Table#
pairs 和 ipairs 功能初探#
pairs 和 ipairs 是两个标准库中的函数, 用于从 Table 数据结构中遍历元素. 简单说来, pairs 是用于遍历 Hash Table (类似于 Python dict) 中的 key, value pair 的, 类似于 Python 中的 dict.items() 方法. 而 ipairs 是用于遍历 Array Table (类似于 Python list) 中的 index 和 item 的, 类似于 Python 中的 enumerate(list) 方法.
下面是从 官方文档 中摘抄的定义.
pairs (t)
如果 t 有元方法 __pairs, 以 t 为参数调用它, 并返回其返回的前三个值.
否则, 返回三个值: next 函数, 表 t, 以及 nil. 因此以下代码:
for k, v in pairs(t) do body end
能迭代表 t 中的所有键值对.
参见函数 next 中关于迭代过程中修改表的风险.
ipairs (t)
返回三个值 (迭代函数, 表 t 以及 0 ), 如此, 以下代码:
for i,v in ipairs(t) do body end
将迭代键值对(1, t[1]), (2, t[2]), … , 直到第一个空值.
下面是一个大多数人使用这两个函数的例子
test0.lua
1#!/usr/bin/env lua
2
3--[[
4pairs 和 ipairs 的常见用法.
5--]]
6
7
8--[[
9可能的输出 (顺序可能不同):
10
11key = a, value = 100, arg3 = nil
12key = c, value = 300, arg3 = nil
13key = b, value = 200, arg3 = nil
14--]]
15print("===== pairs =====")
16local pythonDict = {a = 100, b = 200, c = 300}
17for key, value in pairs(pythonDict) do
18 print(string.format("key = %s, value = %s", key, value))
19end
20
21--[[
22输出 (Lua 中 index 是从 1 开始的):
23
24index = 1, value = a
25index = 2, value = b
26index = 3, value = c
27--]]
28print("===== ipairs =====")
29local pythonList = {"a", "b", "c"}
30for index, value in ipairs(pythonList) do
31 print(string.format("index = %s, value = %s", index, value))
32end
[1]:
import subprocess
subprocess.run(["lua", "test0.lua"]);
===== pairs =====
key = b, value = 200
key = c, value = 300
key = a, value = 100
===== ipairs =====
index = 1, value = a
index = 2, value = b
index = 3, value = c
Example 1#
从这个例子可以看出, 对于 key 不是从 1 开始的整数的 Hash Table, ipairs 没有效果.
test1.lua
1#!/usr/bin/env lua
2
3--[[
4pairs:
5
6- 用于遍历表中的所有键值对
7- 遍历顺序不确定
8- 可以处理任何类型的键(包括字符串、数字等)
9
10ipairs:
11
12- 用于遍历数组部分(即使用连续整数索引的部分)
13- 按照索引的数字顺序遍历
14- 遇到 nil 值或非整数键时停止
15--]]
16
17local pythonDict = {
18 a = 100,
19 b = 200,
20 c = 300,
21}
22
23--[[
24可能的输出 (顺序可能不同):
25
26key = a, value = 100, arg3 = nil
27key = c, value = 300, arg3 = nil
28key = b, value = 200, arg3 = nil
29--]]
30
31print("===== pairs =====")
32for arg1, arg2, arg3 in pairs(pythonDict) do
33 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
34end
35
36--[[
37输出: (无输出)
38解释: 由于这个表没有使用整数索引, ipairs 不会遍历任何元素.
39--]]
40print("===== ipairs =====")
41for arg1, arg2, arg3 in ipairs(pythonDict) do
42 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
43end
[2]:
subprocess.run(["lua", "test1.lua"]);
===== pairs =====
key = a, value = 100, arg3 = nil
key = b, value = 200, arg3 = nil
key = c, value = 300, arg3 = nil
===== ipairs =====
Example 2#
从这个例子可以看出, 对于 key 不是从 1 开始的整数的 Hash Table, ipairs 没有效果. 只要数字不是 1, 2, 3, …, 就不可以. 因为它本质上是返回 (1, table[1]), (2, table[2]), … 直到碰到第一个 nil 为止. 在这种情况下第一个就是 nil, 所以什么也没有返回.
test2.lua
1#!/usr/bin/env lua
2
3local pythonDict = {
4 [100] = "a",
5 [200] = "b",
6 [300] = "3",
7}
8
9--[[
10输出:
11
12key = 300, value = 3, arg3 = nil
13key = 100, value = a, arg3 = nil
14key = 200, value = b, arg3 = nil
15--]]
16print("===== pairs =====")
17for arg1, arg2, arg3 in pairs(pythonDict) do
18 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
19end
20
21--[[
22输出: (无输出)
23解释: 由于这个表没有使用整数索引, ipairs 不会遍历任何元素.
24--]]
25print("===== ipairs =====")
26for arg1, arg2, arg3 in ipairs(pythonDict) do
27 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
28end
[3]:
subprocess.run(["lua", "test2.lua"]);
===== pairs =====
key = 300, value = 3, arg3 = nil
key = 100, value = a, arg3 = nil
key = 200, value = b, arg3 = nil
===== ipairs =====
Example 3#
对于 key 是从整数开始的 Hash Table, ipairs 是有效果的.
test3.lua
1#!/usr/bin/env lua
2
3local pythonDict = {
4 [1] = "a",
5 [2] = "b",
6 [3] = "c",
7}
8
9print("===== pairs =====")
10for arg1, arg2, arg3 in pairs(pythonDict) do
11 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
12end
13
14--[[
15由于该表采用了整数索引, 所以可以用 ipairs. 输出:
16
17key = 1, value = a, arg3 = nil
18key = 2, value = b, arg3 = nil
19key = 3, value = c, arg3 = nil
20--]]
21print("===== ipairs =====")
22for arg1, arg2, arg3 in ipairs(pythonDict) do
23 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
24end
[4]:
subprocess.run(["lua", "test3.lua"]);
===== pairs =====
key = 3, value = c, arg3 = nil
key = 1, value = a, arg3 = nil
key = 2, value = b, arg3 = nil
===== ipairs =====
key = 1, value = a, arg3 = nil
key = 2, value = b, arg3 = nil
key = 3, value = c, arg3 = nil
Example 4#
从这个例子可以看出, 对于 Array Table, pairs 返回的 key 会是 1, 2, 3, …
test4.lua
1#!/usr/bin/env lua
2
3local pythonList = {
4 "a",
5 "b",
6 "c"
7}
8
9--[[
10输出:
11
12key = 1, value = a, arg3 = nil
13key = 2, value = b, arg3 = nil
14key = 3, value = c, arg3 = nil
15--]]
16print("===== pairs =====")
17for arg1, arg2, arg3 in pairs(pythonList) do
18 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
19end
20
21--[[
22输出:
23
24key = 1, value = a, arg3 = nil
25key = 2, value = b, arg3 = nil
26key = 3, value = c, arg3 = nil
27--]]
28print("===== ipairs =====")
29for arg1, arg2, arg3 in ipairs(pythonList) do
30 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
31end
32
33--[[
34对于列表, 输出就是 index 和 value, 跟 python 中的 enumerate 函数类似. 输出:
35
36key = 1, value = a
37key = 2, value = b
38key = 3, value = c
39--]]
40print("===== ipairs =====")
41for arg1, arg2 in ipairs(pythonList) do
42 print(string.format("key = %s, value = %s", arg1, arg2))
43end
[5]:
subprocess.run(["lua", "test4.lua"]);
===== pairs =====
key = 1, value = a, arg3 = nil
key = 2, value = b, arg3 = nil
key = 3, value = c, arg3 = nil
===== ipairs =====
key = 1, value = a, arg3 = nil
key = 2, value = b, arg3 = nil
key = 3, value = c, arg3 = nil
===== ipairs =====
key = 1, value = a
key = 2, value = b
key = 3, value = c
Example 5#
从这个例子可以看出, 对于 Array Table, pairs 返回的 key 会是 1, 2, 3, …
test5.lua
1#!/usr/bin/env lua
2
3local pythonList = {
4 100,
5 200,
6 300
7}
8
9--[[
10输出:
11
12key = 1, value = 100, arg3 = nil
13key = 2, value = 200, arg3 = nil
14key = 3, value = 300, arg3 = nil
15--]]
16print("===== pairs =====")
17for arg1, arg2, arg3 in pairs(pythonList) do
18 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
19end
20
21--[[
22输出:
23
24key = 1, value = 100, arg3 = nil
25key = 2, value = 200, arg3 = nil
26key = 3, value = 300, arg3 = nil
27--]]
28print("===== ipairs =====")
29for arg1, arg2, arg3 in ipairs(pythonList) do
30 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
31end
[6]:
subprocess.run(["lua", "test5.lua"]);
===== pairs =====
key = 1, value = 100, arg3 = nil
key = 2, value = 200, arg3 = nil
key = 3, value = 300, arg3 = nil
===== ipairs =====
key = 1, value = 100, arg3 = nil
key = 2, value = 200, arg3 = nil
key = 3, value = 300, arg3 = nil
Example 6#
test6.lua
1#!/usr/bin/env lua
2
3local pythonList = {
4 1,
5 2,
6 3
7}
8
9--[[
10输出:
11
12key = 1, value = 1, arg3 = nil
13key = 2, value = 2, arg3 = nil
14key = 3, value = 3, arg3 = nil
15--]]
16print("===== pairs =====")
17for arg1, arg2, arg3 in pairs(pythonList) do
18 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
19end
20
21--[[
22输出:
23
24key = 1, value = 1, arg3 = nil
25key = 2, value = 2, arg3 = nil
26key = 3, value = 3, arg3 = nil
27--]]
28print("===== ipairs =====")
29for arg1, arg2, arg3 in ipairs(pythonList) do
30 print(string.format("key = %s, value = %s, arg3 = %s", arg1, arg2, arg3))
31end
[7]:
subprocess.run(["lua", "test6.lua"]);
===== pairs =====
key = 1, value = 1, arg3 = nil
key = 2, value = 2, arg3 = nil
key = 3, value = 3, arg3 = nil
===== ipairs =====
key = 1, value = 1, arg3 = nil
key = 2, value = 2, arg3 = nil
key = 3, value = 3, arg3 = nil
[ ]: