2012-04-29 1 views
3

Есть ли функциональность в Lua, аналогичная collections.defaultdict, доступная в Python, которая автоматически обрабатывает значения по умолчанию для несуществующих ассоциативных ключей массива?Есть ли функция по умолчанию для Python, доступная в Lua

Я хочу, чтобы код ниже устанавливал 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

Отлично! Благодаря :) –

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"