如何在Lua中使用递归迭代器?

我通常可以在LUA中编写想要的迭代器。

但是递归迭代器让我无法解决。

例如,这是一个返回嵌套列表中所有项目的Python递归迭代器:

def items(x):
  if isinstance(x,(list,tuple)):
    for y in x:
      for z in items(y): yield z
  else:
    yield x

for x in items([10,20,[30,[40,50],60],[70,80]]): print(x)

这将打印

10
20
30
40
50
60
70
80

但是我无法在Lua中运行它。我想这是因为我不知道如何从一次迭代到下一次迭代中携带递归遍历的状态。

有什么建议吗?

原文链接 https://stackoverflow.com/questions/70217201

点赞
stackoverflow用户1847592
stackoverflow用户1847592

FP 风格

-- items 函数接收两个参数:tbl 和 outer_iter
local function items(tbl, outer_iter)
   -- 定义一个局部变量 index 并初始化为 0
   local index = 0
   -- 定义内部函数 iter
   local function iter()
      index = index + 1
      return tbl[index]
   end
   -- 返回一个函数,用于遍历 tbl 中的元素
   return function()
      while iter do
         local v = iter()
         if v == nil then
            -- 如果 tbl 遍历完毕,则切换到 outer_iter
            iter, outer_iter = outer_iter
         elseif type(v) == "table" then
            -- 如果元素是一个表,则递归调用 items 函数
            iter = items(v, iter)
         else
            -- 如果元素是一个普通值,则返回该值
            return v
         end
      end
   end
end

协程风格

local function items(tbl)
   -- 使用 coroutine.wrap 函数创建一个协程
   return coroutine.wrap(
      function()
         -- 遍历 tbl 中的每个元素
         for _, v in ipairs(tbl) do
            if type(v) == "table" then
               -- 如果元素是一个表,则递归调用 items 函数,并遍历表中的元素
               local iter = items(v)
               local v = iter()
               while v ~= nil do
                  coroutine.yield(v)
                  v = iter()
               end
            else
               -- 如果元素是一个普通值,则直接返回该值
               coroutine.yield(v)
            end
         end
      end
   )
end

使用示例:

for x in items{10,20,{30,{},{40,50},60},{70,80}} do
   print(x)
end
2021-12-03 17:15:34