Page 1 of 2
Nested Table Iterator
Posted: Tue Dec 30, 2014 5:15 pm
by adrix89
I need a fancy iterator that traverses through all the nested tree of a table.
I preferably want this with an iterator factory so that it can be reused.
Something like this
Code: Select all
table = {{{ stuff=value},{}}, {{{},{stuff=value2}}} ,{},{{}}}
iter_function = whatver magic is here
local stuff
for tbl in iter_function(table) do
stuff = tbl.stuff
end
Re: Nested Table Iterator
Posted: Tue Dec 30, 2014 6:52 pm
by Muris
I guess youre not accepting recursive function as an answer and passing a function inside? Something along the line of:
Code: Select all
local table = {{{ stuff=value},{}}, {{{},{stuff=value2}}} ,{},{{}}}
local function iter( t, fn )
fn(t)
for v,k in pairs( t ) do
if type(k) == "table" then
iter( k, fn )
end
end
end
iter( table, print )
When traversing nested tables, I feel that recursion is the way to go and passing a function parameter you probably could make it quite dynamic, but I don't think you can make one for all solution to it.
At least I guess it would be a start to your question, maybe not complete solution. Also you could take a look at next(i,v) for creating an iterator.
http://www.lua.org/manual/2.4/node31.html
Re: Nested Table Iterator
Posted: Tue Dec 30, 2014 9:01 pm
by adrix89
Recursion is probably mandatory for this thing.
What I want is some wizardry to make it work with for and be generic.
I already have a reclusive function solution for the problem.
Your solution is pretty good,better then what I have currently.
Re: Nested Table Iterator
Posted: Tue Dec 30, 2014 10:33 pm
by Azhukar
adrix89 wrote:I need a fancy iterator that traverses through all the nested tree of a table.
Something like this? Your example didn't really make sense.
Code: Select all
local function process(value,key)
if (type(value)=="table") then
for k,v in pairs(value) do
process(v,k)
end
else
coroutine.yield(key,value)
end
end
local function tree(root)
return coroutine.wrap(process),root
end
function love.load()
local test = {{{ stuff=123},{}}, {{{},{stuff=345}}} ,{},{{}}}
for leaf,value in tree(test) do
print(leaf,value)
end
end
Re: Nested Table Iterator
Posted: Tue Dec 30, 2014 10:55 pm
by adrix89
Azhukar wrote:adrix89 wrote:I need a fancy iterator that traverses through all the nested tree of a table.
Something like this? Your example didn't really make sense.
Code: Select all
local function process(value,key)
if (type(value)=="table") then
for k,v in pairs(value) do
process(v,k)
end
else
coroutine.yield(key,value)
end
end
local function tree(root)
return coroutine.wrap(process),root
end
function love.load()
local test = {{{ stuff=123},{}}, {{{},{stuff=345}}} ,{},{{}}}
for leaf,value in tree(test) do
print(leaf,value)
end
end
I am not sure, the reason I wanted tbl is because I wanted to evaluate at any point of the tables.
This looks like it will only get stuff key not the individual tables.
In reality I am using a class systems with lots of variables and functions and references contained in the table and the access to the table tree that I want iterated is in the form of table.children.
Its getting closer to what I want.
Re: Nested Table Iterator
Posted: Wed Dec 31, 2014 12:52 am
by Azhukar
adrix89 wrote:I am not sure, the reason I wanted tbl is because I wanted to evaluate at any point of the tables.
This looks like it will only get stuff key not the individual tables.
In reality I am using a class systems with lots of variables and functions and references contained in the table and the access to the table tree that I want iterated is in the form of table.children.
Its getting closer to what I want.
Hence why I said your example doesn't make sense, you have to define what values you want to work with in your for loop. I can tell you straight up at this point you're doing something incredibly wrong.
Re: Nested Table Iterator
Posted: Wed Dec 31, 2014 8:58 am
by adrix89
Yes! I manged to modify it to work.
Code: Select all
local function process(value)
if (type(value)=="table") then
coroutine.yield(value)
for k,v in pairs(value) do
process(v)
end
end
end
local function traverse(root)
return coroutine.wrap(process),root
end
function love.load()
local test = { { {x, stuff=123},{x,stuff=3 }}, {stuff=23 ,{ {x },{x, stuff=345}}} ,{x,stuff=1},{ {x }}}
for tbl in traverse(test) do
print(tbl.stuff)
end
end
Re: Nested Table Iterator
Posted: Wed Dec 31, 2014 11:28 am
by Muris
I can give you another solution just modifying my original post. Here we are passing a function as a parameter, because this way you only need to traverse the whole table through once unlike on the solution where you build new table, then traverse that table through
Code: Select all
local test = { { {x, stuff=123},{x,stuff=3 }}, {stuff=23 ,{ {x },{x, stuff=345}}} ,{x,stuff=1},{ {x }}}
local table = {{{ stuff=value},{}}, {{{},{stuff=value2}}} ,{},{{}}}
local function iter( t, fn )
fn(t)
for v,k in pairs( t ) do
if type(k) == "table" then
iter( k, fn )
end
end
end
function love.load()
print( "Table!")
iter( table, (function( f ) print(f.stuff) end ) )
print( "Test!")
iter( test, (function( f ) print(f.stuff) end ) )
-- Or bit more complicated, summing all stuff values:
local sum = 0
iter( test,
( function( f )
if( f.stuff ) then
sum = sum + f.stuff
end
end ) )
print( "sum:" .. sum)
end
Re: Nested Table Iterator
Posted: Wed Dec 31, 2014 2:03 pm
by Azhukar
Muris wrote:unlike on the solution where you build new table
There is no such solution in this thread.
Re: Nested Table Iterator
Posted: Thu Jan 01, 2015 6:45 am
by ivan
One problem with iterating nested tables is that (usually) you need to know the 'scope' in addition to the key and the value.
A while ago I wrote a library for accessing nested tabled. It uses "cocatecated sting keys" as
described here. Just make sure to get the code from
the repo as the version on the forums may be slightly out of date.
It works with cyclic tables too.
Recursion is probably mandatory for this thing.
My implementation is non-recursive (see
table.gckeys). I used breadth-first traversal with a queue.