在
for
循环中,使用 pairs()
与 ipairs()
循环有什么区别?
《Lua 编程》book 提到了两者,但是,两者似乎都生成类似的输出,如下所示:
使用
ipairs()
:
a = {"one", "two", "three"}
for i, v in ipairs(a) do
print(i, v)
end
输出:
1 one
2 two
3 three
使用
pairs()
:
a = {"one", "two", "three"}
for i, v in pairs(a) do
print(i, v)
end
输出:
1 one
2 two
3 three
ipairs()
和 pairs()
略有不同,如您在 手册参考 中所见。
技术性较低的描述可能是:
ipairs()
返回索引值对,主要用于数字表。
非数字键将被整体忽略,类似于小于 1 的数字索引。
此外,指数之间的差距也会导致停牌。
排序是确定的,按数值大小排列。
pairs()
返回键值对,主要用于关联表。
所有密钥均被保留,但顺序未指定。
此外,虽然
pairs()
可用于获取表的大小(请参阅另一个问题),但使用 ipairs()
来执行同一任务是不安全的,因为它可能会丢失一些键。
以下代码片段说明了两个选项之间的差异。
> u = {}
> u[-1] = "y"
> u[0] = "z"
> u[1] = "a"
> u[3] = "b"
> u[2] = "c"
> u[4] = "d"
> u[6] = "e"
> u["hello"] = "world"
>
> for key, value in ipairs(u) do print(key, value) end
1 a
2 c
3 b
4 d
>
> for key, value in pairs(u) do print(key, value) end
1 a
2 c
3 b
4 d
6 e
0 z
hello world
-1 y
>
正如我们在示例中看到的,虽然
pairs()
的所有键都出现在输出中,但 ipairs()
缺少一些键:
hello
因为它不是数字键;
-1
和 0
,因为尽管它们是数字,但它们的值小于 1,并且;
6
假设我们隐含地拥有 u[5] = nil
,并且在迭代时找到 nil 值正是 ipairs()
的结束条件。
最后,请注意,如您的示例中所示,当您创建表而不指定任何键(例如
a = {"one", "two", "three"}
)时,从 1 开始的数字键将隐式分配给每个值,即定义被理解为 a = { [1] = "one", [2] = "two", [3] = "three" }
。
因此,在这些场景中使用 pairs()
或 ipairs()
基本上是相同的,除了 pairs()
的非保证顺序之外。
Lua 中没有
array
类型,只有 table
可能具有从索引 1 开始的连续元素。实现甚至针对该用途进行了优化。
与数字 for 循环相比,通用 for 循环需要三个值:
它使用上下文值和索引值调用可调用函数,将所有返回值存储在提供的新变量中。第一个另外保存为新的索引值。
现在是循环可调用的一些代表性示例:
ipairs(t)
返回一个函数、表格 t
和起点 0
。function ipairs_next(t, i)
i = i + 1
var v = t[i]
if v ~= nil then
return i, v
end
end
因此,会显示从 1 开始直到第一个缺失的所有数字条目。
pairs(t)
要么委托给 t
的元表,特别是 __pairs(t)
,要么返回函数 next
、表 t
和起点 nil
。next
接受一个表和一个索引,并返回下一个索引和关联值(如果存在)。
因此,所有元素都以某种任意顺序显示。
人们对函数的创造性是没有限制的,这正是 vanilla Lua 所期望的。
请参阅“*https://stackoverflow.com/questions/23350281/bizzare-attempt-to-call-a-table-value-in-lua*”,了解用户编写的可调用对象的示例,以及某些方言如何如果第一个值实际上不是可调用的,则做出反应。