如何检查一个表是否包含某个键__index?

我想优化一个斐波那契函数,但使用表索引和备忘录似乎是一种好的方法(迭代也很好)...然而,很快我遇到了问题:我不能确定一个键是否在表中。我该如何做到这一点?

local fib = {}

function fib_index(t, k)
   if k == 0 or k == 1 then
      t[k] = k
   else
      t[k] = t[k-1] + t[k-2]
   end
   return t[k]
end
setmetatable(fib, {__index = fib_index})
点赞
用户5697743
用户5697743

你的代码在当前状态下可以正常运行。背后的原因是,已经存储的值比 __index 元方法具有更高的优先级,因此如果值存在,它会立即返回。有一些优化可以使你的代码看起来更好:

local fib = setmetatable({1, 1}, {__index = function(t,k)
    assert(k > 0, 'Invalid fib index') -- 最基本的检查
    local res = t[k-1] + t[k-2]
    t[k] = res
    return res
end})

在这里,我完全删除了函数声明(如果你想重用它,请考虑使用 local function 来使你的函数成为本地变量而不是全局变量),通过在表声明中直接添加初始值(没有索引 0,以保持 Lua 风格,结果中也没有零),并利用了 setmetatable 返回最初传递的表这一事实,使代码更加简单。你可以删除 assert,但最好看到有意义的错误消息,而不是 "stack overflow"。

而且如果你 真的 想检查在表中是否存在值(此代码 不需要 这样做),可以使用 rawget

rawget(fib, 10) == nil

会告诉你是否已经计算并缓存 10

2019-03-21 10:14:09