On this page

Lua 迭代器

Lua 迭代器详解

迭代器是 Lua 中用于遍历集合元素的一种机制,它提供了一种顺序访问集合元素的方法,而不需要暴露底层数据结构。

1. 迭代器基本概念

迭代器由三部分组成:

  1. 迭代函数:每次调用返回下一个元素
  2. 不可变状态:迭代过程中不变的数据
  3. 控制变量:当前迭代状态

2. Lua 内置迭代器

pairs() 迭代器

  • 遍历表中所有键值对
  • 不保证顺序
  • 适合遍历非数组表
local t = {a=1, b=2, c=3}
for key, value in pairs(t) do
    print(key, value)
end
-- 可能输出:
-- a    1
-- c    3
-- b    2

ipairs() 迭代器

  • 遍历数组部分(连续数字索引)
  • 从1开始到第一个nil结束
  • 保证顺序
local arr = {"a", "b", "c"}
for index, value in ipairs(arr) do
    print(index, value)
end
-- 输出:
-- 1    a
-- 2    b
-- 3    c

3. 自定义迭代器

无状态迭代器

-- 平方数迭代器
local function square(iteratorMaxCount, currentNumber)
    if currentNumber < iteratorMaxCount then
        currentNumber = currentNumber + 1
        return currentNumber, currentNumber * currentNumber
    end
end

-- 使用迭代器
for i, sq in square, 5, 0 do
    print(i, sq)
end
-- 输出:
-- 1    1
-- 2    4
-- 3    9
-- 4    16
-- 5    25

有状态迭代器

-- 创建迭代器工厂
local function arrayIter(array)
    local index = 0
    local length = #array
    return function() -- 迭代函数
        index = index + 1
        if index <= length then
            return index, array[index]
        end
    end
end

-- 使用迭代器
local fruits = {"apple", "banana", "orange"}
for i, fruit in arrayIter(fruits) do
    print(i, fruit)
end
-- 输出:
-- 1    apple
-- 2    banana
-- 3    orange

4. 文件行迭代器

-- 逐行读取文件
for line in io.lines("example.txt") do
    print(line)
end

5. 字符串模式匹配迭代器

local s = "hello world from Lua"

-- 查找所有单词
for word in string.gmatch(s, "%a+") do
    print(word)
end
-- 输出:
-- hello
-- world
-- from
-- Lua

6. 协程迭代器

-- 使用协程创建迭代器
local function permgen(a, n)
    n = n or #a
    if n <= 1 then
        coroutine.yield(a)
    else
        for i = 1, n do
            a[n], a[i] = a[i], a[n]
            permgen(a, n - 1)
            a[n], a[i] = a[i], a[n]
        end
    end
end

-- 排列迭代器
local function permutations(a)
    local co = coroutine.create(function() permgen(a) end)
    return function()
        local code, res = coroutine.resume(co)
        return res
    end
end

-- 使用迭代器
for p in permutations({"a", "b", "c"}) do
    print(table.concat(p, ", "))
end

7. 迭代器性能考虑

  1. 无状态迭代器通常比有状态迭代器更高效
  2. 避免在迭代过程中修改表(可能导致不可预测行为)
  3. ipairs比pairs快(因为只遍历数组部分)

8. 常见迭代器模式

过滤迭代器

-- 只返回偶数的迭代器
local function evens(array)
    local i = 0
    return function()
        i = i + 1
        while i <= #array do
            if array[i] % 2 == 0 then
                return array[i]
            end
            i = i + 1
        end
    end
end

-- 使用迭代器
for num in evens({1,2,3,4,5,6}) do
    print(num)
end
-- 输出:
-- 2
-- 4
-- 6

映射迭代器

-- 将数组元素加倍的迭代器
local function double(array)
    local i = 0
    return function()
        i = i + 1
        if i <= #array then
            return array[i] * 2
        end
    end
end

-- 使用迭代器
for num in double({1,2,3}) do
    print(num)
end
-- 输出:
-- 2
-- 4
-- 6

Lua 的迭代器机制非常灵活,可以创建各种复杂的数据遍历方式,同时保持代码的简洁性和可读性。