Nested Table Iterator

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
adrix89
Party member
Posts: 135
Joined: Fri Oct 15, 2010 10:58 am

Nested Table Iterator

Post 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
I use Workflowy but you can check out Dynalist as its the better offer.
Muris
Party member
Posts: 131
Joined: Fri May 23, 2014 9:18 am

Re: Nested Table Iterator

Post 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
User avatar
adrix89
Party member
Posts: 135
Joined: Fri Oct 15, 2010 10:58 am

Re: Nested Table Iterator

Post 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.
I use Workflowy but you can check out Dynalist as its the better offer.
User avatar
Azhukar
Party member
Posts: 478
Joined: Fri Oct 26, 2012 11:54 am

Re: Nested Table Iterator

Post 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
User avatar
adrix89
Party member
Posts: 135
Joined: Fri Oct 15, 2010 10:58 am

Re: Nested Table Iterator

Post 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.
I use Workflowy but you can check out Dynalist as its the better offer.
User avatar
Azhukar
Party member
Posts: 478
Joined: Fri Oct 26, 2012 11:54 am

Re: Nested Table Iterator

Post 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.
User avatar
adrix89
Party member
Posts: 135
Joined: Fri Oct 15, 2010 10:58 am

Re: Nested Table Iterator

Post 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
I use Workflowy but you can check out Dynalist as its the better offer.
Muris
Party member
Posts: 131
Joined: Fri May 23, 2014 9:18 am

Re: Nested Table Iterator

Post 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

User avatar
Azhukar
Party member
Posts: 478
Joined: Fri Oct 26, 2012 11:54 am

Re: Nested Table Iterator

Post by Azhukar »

Muris wrote:unlike on the solution where you build new table
There is no such solution in this thread.
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Nested Table Iterator

Post 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.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 5 guests