zoukankan      html  css  js  c++  java
  • Lua迭代器

    迭代器(iterator)是一种可以遍历一个集合中所有元素的代码结构。需要在连续的调用之间保存一些状态,这样才能知道当前迭代器所处的位置及如何从当前位置步进到下一个位置。

    迭代器这个名字多少有点误导性,因为迭代器并没有进行实际的迭代:真正的迭代是循环体完成的,迭代器只不过为每次的迭代提供连续的值。叫“生成器”(generator)可能更好。

    lua使用闭包来表示迭代器。闭包是一个可以访问其自身环境中一个或多个局部变量的函数。这些变量将连续调用过程中的值保存起来,使得闭包能够记住迭代所处的位置。

    闭包通常涉及两个函数:闭包本身和一个用于创建该闭包及其upvalue的工厂(factory)。

    function factory(t)  --用于创建该闭包及其upvalue的工厂
      local i = 0   -- upvalue
      return function()  -- 闭包
        i = i + 1
        return i
      end
    end

    pairs

    对一个table执行pairs函数调用,会有3个返回值:迭代函数,当前table和初始key。泛型for循环内部正是用这3个值来实现对当前table的迭代。

    local t1 = {1,8,h1=nil,h2="earth",5}
    print("[t1] => "..tostring(t1))  -- [t1] => table: 000002C4F4410470
    
    local a1,a2,a3 = pairs(t1)
    print("[a1] => "..tostring(a1)) -- [a1] => function: 00007FF9A60391B0  即迭代函数   对应名为int luaB_next (lua_State *L)的c函数
    print("[a2] => "..tostring(a2)) -- [a2] => table: 000002C4F4410470
    print("[a3] => "..tostring(a3)) -- [a3] => nil  即初始key

    特点: 

    ① 可以遍历table中的所有值不为nil的元素
    ② 不保序:遍历的顺序是随机的
     
    local t1 = {1,8,h1=nil,h2="earth",5}
    local t2 = {k1="go",k2=100}
    local t3 = {10,20,nil,30}
    local t4 = {g1="sun",25,30,nil,35}
    
    print("table t1's length:"..#t1)
    for i,v in pairs(t1) do   -- 对应泛型for,返回的第一个变量i为nil时,循环终止
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t2's length:"..#t2)
    for i,v in pairs(t2) do
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t3's length:"..#t3)    -- 用while循环来模拟泛型for
    local iter,b,c = pairs(t3) -- iter对应名为int luaB_next (lua_State *L)的c函数  b为t3表  c为nil
    while true do
        local i,v = iter(b,c)
        if (i==nil) then
            break 
        end
        print("["..i.."] => "..tostring(v))
    
        c = i
    end
    print("-----------")
    
    print("table t4's length:"..#t4)  -- 用while循环来模拟泛型for
    local m, n
    local iterr = pairs(t4)
    while true do
        m, n = iterr(t4,m)
        if (m==nil) then
            break 
        end
        print("["..m.."] => "..tostring(n))
    end
    print("-----------")

    输出结果如下:

    table t1's length:3
    [1] => 1
    [2] => 8
    [3] => 5
    [h2] => earth
    -----------
    table t2's length:0
    [k2] => 100
    [k1] => go
    -----------
    table t3's length:4
    [1] => 10
    [2] => 20
    [4] => 30
    -----------
    table t4's length:4
    [1] => 25
    [2] => 30
    [4] => 35
    [g1] => sun
    -----------

    实现自己的pairs闭包

    local t1 = {1,8,h1=nil,h2="earth",5}
    local t2 = {k1="go",k2=100}
    local t3 = {10,20,nil,30}
    local t4 = {g1="sun",25,30,nil,35}
    
    function mypairs(t)
        return next, t, nil
    end
    
    print("table t1's length:"..#t1)
    for i,v in next, t1, nil do  -- 对应泛型for,返回的第一个变量i为nil时,循环终止
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t2's length:"..#t2)
    for i,v in mypairs(t2) do
      print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t3's length:"..#t3)  -- 用while循环来模拟泛型for
    local myiter,b,c = mypairs(t3)
    while true do
        local i,v = myiter(b,c)
        if (i==nil) then
            break 
        end
        print("["..i.."] => "..tostring(v))
    
        c = i
    end
    print("-----------")
    
    print("table t4's length:"..#t4)  -- 用while循环来模拟泛型for
    local m, n
    while true do
        m, n = next(t4,m)
        if (m==nil) then
            break 
        end
        print("["..m.."] => "..tostring(n))
    end
    print("-----------")
    ipairs
    对一个table执行ipairs函数调用,会有3个返回值:迭代函数,当前table和初始索引。泛型for循环内部正是用这3个值来实现对当前table的迭代。
    local t1 = {1,8,h1=nil,h2="earth",5}
    print("[t1] => "..tostring(t1))  -- [t1] => table: 0000019EC28B8020
    
    local a1,a2,a3 = ipairs(t1)
    print("[a1] => "..tostring(a1)) -- [a1] => function: 00007FF9A0559410  即迭代函数   对应名为static int ipairsaux (lua_State *L)的c函数
    print("[a2] => "..tostring(a2)) -- [a2] => table: 0000019EC28B8020
    print("[a3] => "..tostring(a3)) -- [a3] => 0  即初始索引

    特点: 

    ① 只能遍历table中的数组元素
    ② table中某个数组元素为nil,则table的遍历会终止
    ③ 保序:遍历的顺序与存放的顺序一致
     
    local t1 = {1,8,h1=nil,h2="earth",5}
    local t2 = {k1="go",k2=100}
    local t3 = {10,20,nil,30}
    local t4 = {g1="sun",25,30,nil,35}
    
    print("table t1's length:"..#t1)
    for i,v in ipairs(t1) do   -- 对应泛型for,返回的第一个变量i为nil时,循环终止
      print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t2's length:"..#t2)
    for i,v in ipairs(t2) do
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t3's length:"..#t3)    -- 用while循环来模拟泛型for
    local iter,b,c = ipairs(t3) -- iter对应名为static int ipairsaux (lua_State *L)的c函数  b为t3表  c为0
    while true do
        local i,v = iter(b,c)
        if (i==nil) then
            break 
        end
        print("["..i.."] => "..tostring(v))
    
        c = c + 1
    end
    print("-----------")
    
    print("table t4's length:"..#t4)  -- 用while循环来模拟泛型for
    local m = 0
    local n = nil
    local iterr = ipairs(t4) -- iter对应名为static int ipairsaux (lua_State *L)的c函数
    while true do
        m, n = iterr(t4,m)
        if (m==nil) then
            break 
        end
        print("["..m.."] => "..tostring(n))
    end
    print("-----------")

    输出结果如下:

    table t1's length:3
    [1] => 1
    [2] => 8
    [3] => 5
    -----------
    table t2's length:0
    -----------
    table t3's length:4
    [1] => 10
    [2] => 20
    -----------
    table t4's length:4
    [1] => 25
    [2] => 30
    -----------

    实现自己的ipairs闭包(方式①)

    local t1 = {1,8,h1=nil,h2="earth",5}
    local t2 = {k1="go",k2=100}
    local t3 = {10,20,nil,30}
    local t4 = {g1="sun",25,30,nil,35}
    
    function myipairs(t)
        local i = 0
        return function()
            i = i + 1
            if (t[i]~=nil) then
                return i, t[i]
            end
        end
    end
    
    print("table t1's length:"..#t1)
    for i,v in myipairs(t1) do  -- 对应泛型for,返回的第一个变量i为nil时,循环终止
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t2's length:"..#t2)
    for i,v in myipairs(t2) do
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t3's length:"..#t3)
    for i,v in myipairs(t3) do
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t4's length:"..#t4)  -- 用while循环来模拟泛型for
    local myiter = myipairs(t4)
    while true do
        local i,v = myiter()
        if (i==nil) then
            break 
        end
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")

    实现自己的ipairs闭包(方式②)

    local t1 = {1,8,h1=nil,h2="earth",5}
    local t2 = {k1="go",k2=100}
    local t3 = {10,20,nil,30}
    local t4 = {g1="sun",25,30,nil,35}
    
    function myiter(t, i)
        i = i + 1
        if (t[i]~=nil) then
            return i, t[i]
        end
    end
    
    function myipairs2(t)
        return myiter, t, 0
    end
    
    print("table t1's length:"..#t1)
    for i,v in myiter, t1, 0 do  -- 对应泛型for,返回的第一个变量i为nil时,循环终止
        print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t2's length:"..#t2)
    for i,v in myipairs2(t2) do
      print("["..i.."] => "..tostring(v))
    end
    print("-----------")
    
    print("table t3's length:"..#t3)  -- 用while循环来模拟泛型for
    local myiter,b,c = myipairs2(t3)
    while true do
        local i,v = myiter(b,c)
        if (i==nil) then
            break 
        end
        print("["..i.."] => "..tostring(v))
    
        c = c + 1
    end
    print("-----------")
    
    print("table t4's length:"..#t4)  -- 用while循环来模拟泛型for
    local m = 0
    local n = nil
    while true do
        m, n = myiter(t4, m)
        if (m==nil) then
            break
        end
        print("["..m.."] => "..tostring(n))
    end
    print("-----------")

  • 相关阅读:
    IE9不能在线打开InfoPath表单的解决办法
    在Word中使用Quick Parts功能
    .NET WinForm程序在Windows7下实现玻璃效果和任务栏进度条效果
    如何对已经发布过的InfoPath模板进行修改
    .NET WinForm中给DataGridView自定义ToolTip并设置ToolTip的样式
    有关SharePoint Client Object应用的笔记
    解决VS 2010中编译程序时弹出"Type universe cannot resolve assembly"的错误
    SharePoint客户端对象模型"(400) Bad Request"错误
    C# Method Attribute and Reflection
    .NET WinForm下一个支持更新ProgressBar进度的DataGridView导出数据到Excel的类
  • 原文地址:https://www.cnblogs.com/kekec/p/14320433.html
Copyright © 2011-2022 走看看