[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Mapping values from one table to another
- From: Rici Lake <lua@...>
- Date: Mon, 12 Mar 2007 19:26:45 -0500
Greg Bakker wrote:
Hi,
I'm curious as to how best to create a table via a direct mapping from
another.
For example, say you want
{ 1, 2, 3 } => { {name="something1", value=1}, {name="something2",
value=2}, {name="something3", value=3} }
Currently I'm using
function map(f, v, ...)
if v then
return f(v), map(f, ...)
end
end
function func(v) return {name="something"..v, value=v} end
a = { 1, 2, 3 }
b = { map(func, unpack(a)) }
which is probable stack abuse. Is there a canonical approach; maybe a
better way is to use a loop and insert-at-end?
Thanks,
Greg Bakker
My preference is that map transforms an iterator into an iterator rather
than a table into a table.
Simplified implementation (better code is part of a Gem I'm writing):
Note: f,o,s is an iterator triple (nextfunc, object, state); i.e. the
triple provided to a 'for' statement.
function map(func, f, o, s)
local function aux(k, ...)
if k ~= nil then
return k, func(...)
end
end
local function nexter(o, s)
return aux(f(o, s))
end
return nexter, o, s
end
This 'map' is called with a function and an iterator, and
returns an iterator.
function func(v) return {name = "something"..v, value = v} end
local a = {10, 20, 30}
local b = {}
for k, v in map(func, ipairs(a)) do b[k] = v end
Note that this implementation of map is composable:
function inflate(v) return {name = v.name, value = v.value * 1.05} end
for k, v in map(inflate, map(func, ipairs(a)) do ... end
Often, we actually want a fold (collector):
function collect(t, f, o, s)
for k, v in f, o, s do t[k] = v end
return t
end
So that we can then write:
b = collect({}, map(inflate, map(func, ipairs(a))))
The nice thing is that this will work with any iterator, not just ipairs.