教程 |
|
for
语句有两种不同的形式。一种可以用于遍历数字序列,另一种可以用于遍历称为迭代器的函数。for
语句在参考手册的 2.4.5 节中介绍。 [1]
for
的数字序列版本具有以下语法
for
变量 =
起始表达式 ,
结束表达式 [,
步长表达式] do
代码块 end
该语句在进入 for
代码块之前将变量的值设置为起始表达式。只有当变量的值没有超过最后一个值结束表达式时,才会进入代码块。这包括循环第一次迭代时。每次代码块退出时,步长表达式都会加到变量上。指定步长表达式是可选的。如果没有指定,则使用 1 的值。例如,
> for i = 1,3 do print(i) end -- count from 1 to 3 1 2 3 > for i = 3,1 do print(i) end -- count from 3 to 1 in steps of 1. zero iterations! > for i = 3,1,-1 do print(i) end -- count down from 3 to 1 3 2 1 > for i=1,0,-0.25 do print(i) end -- we're not limited to integers 1 0.75 0.5 0.25 0
i
将是 for
循环范围内的局部变量。即,
> print(i) -- after the above code nil
for v = e1, e2, e3 do block end
等效于以下 Lua 代码
do local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3) if not (var and limit and step) then error() end while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do local v = var block var = var + step end end
for
循环的第二种形式具有以下语法
for
变量 {, 变量} in
表达式列表 do
代码块 end
表达式列表在循环进入之前被评估一次。它的结果是一个迭代器函数(它设置变量的值)、一个状态(从中可以读取值)和一个初始值(从中开始迭代)。
Lua 提供了一个 pairs()
函数来为我们创建表达式列表信息,以便我们迭代一个表。pairs()
函数将允许迭代键值对。请注意,返回项目的顺序没有定义,即使对于索引表也是如此。
> for key,value in pairs(t) do print(key,value) end 3 10 1 3 4 17 2 7 pi 3.14159 banana yellow
ipairs()
函数将允许迭代索引值对。这些是键值对,其中键是数组中的索引。返回元素的顺序保证是索引的数字顺序,非整数键将被简单地跳过。使用与上面示例中相同的表
> for index,value in ipairs(t) do print(index,value) end 1 3 2 7 3 10 4 17
next(table [,index])
函数有助于迭代一个表。当给定一个表和一个索引时,它将返回表中的下一个键值对,例如,
> = next(t) -- index will be nil, the beginning 1 3 > = next(t,4) pi 3.14159
与 pairs()
一样,返回项目的顺序没有定义;索引键可以以任何顺序返回,而不仅仅是按数字递增。pairs()
函数返回一个包含 next()
的表达式列表,因此我们可以迭代表。我们可以将自己的表达式列表传递给 for
语句,如下所示
> for key,value in next,t,nil do print(key,value) end 1 3 2 7 3 10 4 17 pi 3.14159 banana yellow
next,table,nil
作为表达式列表传递给 for
语句。我们在这里说的是,我们想使用迭代器函数 next()
,在表 t
上,从 nil
(开头)开始。for
语句会一直执行,直到 next()
函数返回 nil
(表的结尾)。
Lua 提供了其他有用的迭代器,例如 `io` 库中的 `io.lines([filename])`。我们可以通过创建一个包含一些文本行的自定义文件来演示这一点。
> io.output(io.open("my.txt","w")) > io.write("This is\nsome sample text\nfor Lua.") > io.close()
> for line in io.lines("my.txt") do print(line) end This is some sample text for Lua.
`io` 库提供了另一种遍历文本文件行的方法。
> file = assert(io.open("my.txt", "r")) > for line in file:lines() do print(line) end This is some sample text for Lua. > file:close()
与 `io.lines()` 有什么区别?
您必须显式地打开和关闭文件。这样做的好处之一是,如果文件无法打开,您可以优雅地处理此错误。在这里,`assert` 与 `io.lines` 的效果相同:解释器会停止并显示指向错误行的错误消息;但您可以测试 `file` 的 `nil` 值并执行其他操作。
另一个优点是您可以从任何一行开始循环
file = assert(io.open("list.txt", "r")) local line = file:read() if string.sub(line, 1, 1) ~= '#' then ProcessLine(line) -- File doesn't start with a comment, process the first line end -- We could also loop on the first lines, while they are comment -- Process the remainder of the file for line in file:lines() do ProcessLine(line) end file:close()
我们可以编写自己的迭代器,类似于 `next()`,以迭代任何数据序列。这将在 IteratorsTutorial 中更详细地介绍。