2012-04-29 72 views
3

Lua中是否有类似于Python中可用的collections.defaultdict的功能,它可以自动处理不存在的关联数组键的默认值?Lua中是否有Python的defaultdict功能

我希望下面的代码将nil设置为v而不是错误。所以基本上办法a[2](不存在的键)是table默认:

a = {} 
v = a[2][3] 

>>> PANIC: unprotected error in call to Lua API (main.lua:603: attempt to index field '?' (a nil value)) 

在Python这是可以做到这样的:

>>> import collections 
>>> a = collections.defaultdict(dict) 
>>> print a[2] 
{} 

回答

5

有一个Lua标准函数来做到这一点?不,但你可以用metatables轻松完成。你甚至可以编写一个函数来创建这样的表:

function CreateTableWithDefaultElement(default) 
    local tbl = {} 
    local mtbl = {} 
    mtbl.__index = function(tbl, key) 
    local val = rawget(tbl, key) 
    return val or default 
    end 
    setmetatable(tbl, mtbl) 
    return tbl 
end 

注意,每个元素将得到相同默认值。因此,如果您将默认值设置为表格,则返回表格中的每个“空”元素都将有效地引用同一个表格。如果这不是你想要的,你将不得不修改该功能。

+0

完美!谢谢 :) – 2012-04-29 10:59:39

1

只是以为我会分享我的这段代码的版本,如果有人发现这个需要与表,对象等等兼容的版本。而且,与Nicol的解决方案相反,这实际上在表格中创建了请求的条目。

function defaultdict(default_value_factory) 
    local t = {} 
    local metatable = {} 
    metatable.__index = function(t, key) 
     if not rawget(t, key) then 
      rawset(t, key, default_value_factory(key)) 
     end 
     return rawget(t, key) 
    end 
    return setmetatable(t, metatable) 
end 

用法示例:

d = defaultidct(function() return {} end) 
table.insert(d["people"], {"Bob", "The Builder"}) 

names = defaultdict(function(key) return key end) 
print(names["bob"]) -- bob 
names["bob"] = "bob the builder" 
names["ashley"] = "ashley the fire princess"