For 教程

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
编辑 · 历史
最后编辑于 2017 年 7 月 14 日 上午 6:51 GMT (diff)