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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了