05. 迭代器

一. 泛型迭代器的执行过程

  1. in  后面表达式应返回:迭代函数、状态常量、控制变量; 如果表达式返回的结果个数不足三个会自动用 nil 补足,超出三个的会被忽略。

  2. 向迭代函数 传入两个参数 状态常量、控制变量 ,迭代函数的第一个返回值 如果为nil ,则停止循环 ; 否则第一个返回值 赋值给  控制变量  ,再次循环调用迭代函数

function square(N,j)
    if j < N then
        j = j+1
        return j, j * j
    end
end
--迭代函数: 
--状态常量: 控制迭代函数是否结束
--控制变量: 
--          迭代函数、状态常量 控制变量  
for i,v in   square,      3,       0     do
    print(i,v)
end

--[[
按照执行规则,我们来分析一下上述代码:
(1) in  后面表达式应返回:迭代函数 square、状态常量 3、控制变量 0;  
(2) 向 迭代函数square 传入两个参数 状态常量 3、控制变量0 ,   
第一次调用迭代函数返回1 ,  1*1   (两个值分别赋值给i,v) ,第一个返回值1 不为nil ,则将第一个返回值 赋值给  控制变量(由0变为1)  
再次循环调用迭代函数,状态常量 3、控制变量1 , 迭代函数返回2 ,  2*2   (两个值分别赋值给i,v) ,第一个返回值2 不为nil ,则将第一个返回值 赋值给  控制变量(由1变为2)  
再次循环调用迭代函数,状态常量 3、控制变量2 , 迭代函数返回3 ,  3*3   (两个值分别赋值给i,v) ,第一个返回值3 不为nil ,则将第一个返回值 赋值给  控制变量(由2变为3) 
再次循环调用迭代函数,状态常量 3、控制变量3 , 迭代函数不返回,则为nil  (两个值分别赋值给i,v) ,第一个返回值nil,停止循环。
--]]

 

二. 自定义迭代器

 

--第一种自定义(闭包迭代器)写法:
print("遍历可变长参数列表, 第一种自定义写法 ")
local function ErgodicList3(...)
    local i, t = 0, {n = select("#",...), ...}
    return function()
        if i < t.n then
            i = i + 1
            return i, t[i]
        end
    end
end

for i,j in ErgodicList3(7,nil,nil) do
   print(j)
end

--第二种自定义(迭代器)写法:
print("遍历可变长参数列表, 第二种自定义写法")
--迭代器中的参数是状态常量和控制变量 其中t是状态常量, a是控制变量
local function ErgodicList4(t,a,b)
    if a < t.n then
        a = a + 1
        return a, t[a], b      --返回的第一个返回值必须是控制变量
    end
end

for i, j in ErgodicList4,{10,20,30,n = 3},0 do --这里只能写3个参数, 写多了都是无效的除非使用第一张闭包迭代器
   print(i, j)
end

--pairs迭代器
local function Pairs(t)
    return next, t, nil
end

for i, j in Pairs({1,2,3,4,5,nil,7}) do
    print(i, j) 
end

--也可以写成
for i, j in  next, {1,2,3,4}, nil do
    print(i, j) 
end

 

三. next函数

--[[
    next(table[,indedx]) 遍历表中的所有域
    语法: 
        next(table[,indedx])
    功能: 
        遍历表中值不为nil的所有key和value
        1. 如果值为nil则不会进行返回则会跳过,继续往下寻找
        2. 直到找到非nil的值才回放, 如果遍历完整个表没有寻找到非nil的值则返回nil
    参数: 
        table(必选): 要遍历的表 
        indedx(可选): 键名(key), 默认为nil(返回第一个key和value)
    返回值:
        key和value
--]]

--判断一个表是否为空
do 
    local tb2 = {}
    print("表是否为空:",next(tb2) )
end


do 
    local tb3 = {10,20,30,40}
    --返回索引值1的内容
    --这俩是等价的
    print(next(tb3) )
    print(next(tb3,nil) )
    
    --返回索引值2的内容
    print(next(tb3, 1) )
    
    --返回索引值4的内容
    print(next(tb3, 3) )
    
    --当超过索引值3时, 返回nil
    print(next(tb3, 4) )
end

do 
    local testTbl = {x=10, y=20, z=30}
    local k, v
    repeat
        k, v = next(testTbl, k)
        print(k,v)
    until not k
end

--清空表
do 
    local t = {10,20,30,40,50,60,nil}
    while true do
        local k,v = next(t)
        if not k then break end
        t[k] = nil
    end
    print("----------等同于---------")
    local t = {10,20,30,40,50,60,nil}
    for k,v in next, t,nil do 
        t[k] = nil
    end
end



do 
   print("-------------------------")
   local t = {x=100,y=200,300,nil,400} 
   local a1 = (next(t))              --默认传入nil则从初始化key开始, (先数组然后再表,遇到nil则跳过)
   print(a1)
   local a2 = (next(t,a1))          
   print(a2)
   local a3 = (next(t,a2))          
   print(a3)
   local a4 = (next(t,a3))          
   print(a4)
end

 

posted @ 2022-10-11 17:04  小书臣  阅读(24)  评论(0编辑  收藏  举报