Lua 基础教程(十二)迭代器

95 阅读2分钟

Lua 基础教程(十二)迭代器

hudson 译 原文

迭代器是一种构造,能够遍历所谓的集合或容器的元素。在Lua中,这些集合通常指表,这些表用于创建各种数据结构,如数组。

通用for循环迭代器

通用for循环迭代器提供了集合中每个元素的键值对。下面是一个简单的示例:

array = {"Lua", "Tutorial"}

for key, value in ipairs(array) 
do
   print(key, value)
end

运行上面的代码时,将得到以下输出:

1  Lua
2  Tutorial

上面的示例使用了Lua提供的默认ipairs迭代器函数。

在Lua中,使用函数来表示迭代器。根据这些迭代器函数中维护的状态,有两种主要类型:

  1. 无状态迭代器
  2. 有状态迭代器

无状态迭代器

从名称就可以理解,这种类型的迭代器函数不保留任何状态。

看一个示例创建一个迭代器,使用一个简单的函数打印n 个数字的平方:

function square(iteratorMaxCount, currentNumber)

   if currentNumber < iteratorMaxCount
   then
      currentNumber = currentNumber + 1
      return currentNumber, currentNumber * currentNumber
   end
	
end

for i, n in square, 3, 0
do
   print(i, n)
end

运行上面的程序时,将得到以下输出:

1  1
2  4
3  9

对上面的代码稍做作修改,以模仿迭代器函数ipairs的工作方式。如下所示。

function square(iteratorMaxCount, currentNumber)

   if currentNumber < iteratorMaxCount
   then
      currentNumber = currentNumber + 1
      return currentNumber, currentNumber * currentNumber
   end
	
end

function squares(iteratorMaxCount)
   return square, iteratorMaxCount, 0
end  

for i, n in squares(3)
do 
   print(i, n)
end

运行上面的程序时,将得到以下输出:

1  1
2  4
3  9

有状态迭代器

前面示例中的迭代使用的函数不保留状态。每次调用函数时,它都基于传递给函数的第二个变量返回集合的下一个元素。为了保存当前元素的状态,需要使用闭包。闭包保留跨函数调用的变量值。要创建新的闭包,先创建两个函数,包括闭包本身和工厂,即创建闭包的函数。

下面的代码使用一个闭包创建自己的迭代器:

array = {"Lua", "Tutorial"}

function elementIterator(collection)

   local index = 0
   local count = #collection
	
   -- 返回闭包函数
	
   return function ()
      index = index + 1
		
      if index <= count
      then
         -- 返回迭代器的当前元素
         return collection[index]
      end
		
   end
	
end

for element in elementIterator(array)
do
   print(element)
end

运行上面的程序时,将得到以下输出:

Lua
Tutorial

上面的示例中,可以看到elementIterator内部有另一个方法,它使用了外部的局部变量indexcount,通过每次调用函数时递增索引来返回集合中的每个元素。

可以像上面示例中那样使用闭包创建自己的函数迭代器,并且它可以在每次迭代集合时返回多个元素。