leevis.com icon indicating copy to clipboard operation
leevis.com copied to clipboard

lua 迭代器与泛型for

Open vislee opened this issue 7 years ago • 0 comments

迭代器(iterator)是一种数据结构,能够遍历集合的每个元素。在lua中是一种支持指针类型的结构。

lua中熟知的迭代器有pairsipairs。通常配合泛型for同时使用。

例如:

a = {3, 1, 12}
for i, v in ipairs(a) do
    print(i, v)
end

我们自己也可以实现一个类似于ipairs的功能

function iter (a, i)
    i = i + 1
    local v = a[i]
    if v then
       return i, v
    end
end

function myipairs (a)
    return iter, a, 0
end

使用自定义的迭代器也可以实现类似ipairs的功能

for i, v in myipairs(a) do
    print(i,v)
end

通过自定义的迭代器函数可以看出是泛型for在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。

  • 范性for的执行过程:
    • 首先,初始化,计算in后面表达式的值,表达式应该返回范性for需要的三个值:迭代函数状态常量控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自动用nil补足,多出部分会被忽略。
    • 第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于for结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。
    • 第三,将迭代函数返回的值赋给变量列表。
    • 第四,如果返回的第一个值为nil循环结束,否则执行循环体。
    • 第五,回到第二步再次调用迭代函数。

:loudspeaker: 注: 第二步是真正for循环的开始。第一步只是准备(如果理解了闭包,其实就是调用返回闭包)。迭代器返回的就是控制变量和控制变量对应的值,把上述自定义函数修改一下可能更容易理解。

function iter (a, i)
    local v = a[I+1]
    if v then
       return i+1, v
    end
end

自定义pairs迭代器:

function mypairs(a)
    return next, a, nil
end

自定义限制循环中增加table元素的迭代器

function xpairs(a)
    local size = table.maxn(a)

    local function iter(a, k)
        local t = table.maxn(a)
        if t > size then
            return
        end

        return next(a, k)
    end

    return iter, a, nil
end

--例如
local xx = {1, 2, 3, 4}
for k, v in xpairs(xx) do
    print(k, v)
    -- xx[#xx+1] = v+4
end

自定义限制循环次数的迭代器

function xpairs(a)
    local size = table.maxn(a)
    if size > 32 or size == 0 then
        size = 32
    end

    local t = 0

    local function iter(a, k)
        t = t + 1
        if t > size then
            return
        end

        return next(a, k)
    end

    return iter, a, nil
end

vislee avatar Aug 10 '18 02:08 vislee