教程

lua-users home
wiki

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

表达式列表在循环进入之前被评估一次。它的结果是一个迭代器函数(它设置变量的值)、一个状态(从中可以读取值)和一个初始值(从中开始迭代)。

pairs(table)

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(table)

ipairs() 函数将允许迭代索引值对。这些是键值对,其中键是数组中的索引。返回元素的顺序保证是索引的数字顺序,非整数键将被简单地跳过。使用与上面示例中相同的表

> for index,value in ipairs(t) do print(index,value) end
1       3
2       7
3       10
4       17
请注意,只有表的数组部分被显示,因为只有这些元素具有索引键。

next()

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(表的结尾)。

io.lines()

Lua 提供了其他有用的迭代器,例如 `io` 库中的 `io.lines([filename])`。我们可以通过创建一个包含一些文本行的自定义文件来演示这一点。

> io.output(io.open("my.txt","w"))
> io.write("This is\nsome sample text\nfor Lua.")
> io.close()
我们创建了一个名为“my.txt”的文件,向其中写入三行,然后关闭它。现在我们可以使用 `io.lines` 迭代器读取它
> for line in io.lines("my.txt") do print(line) end
This is
some sample text
for Lua.

file:lines()

`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 中更详细地介绍。


RecentChanges · preferences
edit · history
最后编辑于 2017 年 7 月 14 日下午 12:51 GMT (diff)