• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Lua迭代器

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

迭代器(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("-----------")

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
lua GC 回收效率研究发布时间:2022-07-22
下一篇:
nginx安装lua-nginx-module发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap