我想优化Fibonacci函数,但是使用表索引,memoization似乎是一个很好的方法(迭代也一样好)......然而,很快我遇到了一个问题:我无法确定一个键是否在表中。我怎样才能做到这一点?
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})
您的代码将在其当前状态下正常运行。这背后的原因是,已经有条件的值比__index
元方法具有更高的优先级,所以如果值确实存在,它就会随意返回。很少有优化可以使您的代码看起来更好:
local fib = setmetatable({1, 1}, {__index = function(t,k)
assert(k > 0, 'Invalid fib index') -- Most basic check
local res = t[k-1] + t[k-2]
t[k] = res
return res
end})
在这里我删除函数声明(如果你想重用它,考虑使用local function
而不是function
使你的函数局部化)并通过直接在表声明中添加初始值使代码变得更容易(没有索引0
以保持它的方式,也没有结果为零)并利用setmetatable
最初返回表的事实。如果你愿意,你可以删除assert
,但是看到有意义的错误消息而不是“堆栈溢出”可能是个好主意。
如果你真的想检查表中是否存在值(此代码不需要这个),请使用rawget
:
rawget(fib, 10) == nil
将告诉你10
已经计算和缓存。