function extract_keys( t, ...)
local keys = {}
local potential_keys= {...}
for i,v in ipairs( potential_keys ) do
table.insert(keys, i, t[v])
end
return unpack(keys, 1, #potential_keys)
end
print( extract_keys( { a = 1, b =2, c = 3 }, "a", "b", "xxx", "c", "yyy"))
?
Keith
On Fri, Jul 18, 2008 at 7:26 AM, Alexander Gladysh <
agladysh@gmail.com> wrote:
Hi, list!
I need the function which would work as follows:
print(
extract_keys(
{ a = 1, b = 2, c = 3 },
"a", "b", "xxx", "c", "yyy"
)
)
--> 1 2 nil 3 nil
It is quite simple to write one in C API:
static int Lextract_keys(lua_State * L) {
int nargs = lua_gettop(L);
int i = 2;
luaL_checktype(L, 1, LUA_TTABLE);
for (i = 2; i <= nargs; ++i) {
lua_pushvalue(L, i);
lua_gettable(L, 1);
}
return nargs - 1;
}
However, I'd like to have one in plain Lua. Naïve version follows:
function extract_keys(t, ...)
local results = {}
local nargs = select("#", ...)
for i = 1, nargs do
results[i] = t[select(i, ...)]
end
return unpack(results, 1, nargs) -- Explicitly specifying range
to handle holes in results array
end
It is not quite good enough because it does create an extra table. Is
there a better way to implement it except to generate code as follows?
do
local function generate_extractor(n)
assert(type(n) == "number")
local a, r = {}, {}
for i = 1, n do
a[i], r[i] = 'a'..i, 't[a'..i..']'
end
return assert(
loadstring(
[[return function(t,]]..table.concat(a,
",")..[[)return ]]..table.concat(r, ",").."end",
"extract_keys_"..n
)
)()
end
local extractors = setmetatable(
{
[0] = function(t) end;
[1] = function(t, a1) return t[a1] end;
[2] = function(t, a1, a2) return t[a1], t[a2] end;
[3] = function(t, a1, a2, a3) return t[a1], t[a2], t[a3] end;
[4] = function(t, a1, a2, a3, a4) return t[a1], t[a2],
t[a3], t[a4] end;
[5] = function(t, a1, a2, a3, a4, a5) return t[a1], t[a2],
t[a3], t[a4], t[a5] end;
},
{
__index = function(t, k)
local v = generate_extractor(k)
rawset(t, k, v)
return v
end
}
)
function extract_keys(t, ...)
return extractors[select("#", ...)](t, ...)
end
end
Assuming that we're extremely rarely need to use that __index stub,
and we always can add more hand-written default entries.
TIA,
Alexander.