recursive array loop?
BlitzMax Forums/BlitzMax Beginners Area/recursive array loop?
| ||
hi, i am trying to make a recursive function that loops through a multidimensional array, i've found this PHP code Function loop($array, $parent=''){ foreach( $array as $option => $value ){ If( $parent != '' ){ $option = $parent . '[' . $option . ']'; } If( is_array($value) ){ loop($value, $option); } Else { ?> <div><?php echo $option; ?> = <?php echo $value; ?></div> <?php } } } loop ( $names ); i am still learning the blitzmax syntax and do not know php very well, so i am struggling with porting the php idea to blitzmax...is it even possible? or is the array handling in blitzmax too different? |
| ||
Why do you need recursion? Don't you know how many dimensiosn your array has, so you can just use nested for-next loops? |
| ||
A problem I can see is that BMax requires you to know the type of array, the arrays in PHP can hold variable values. You *could* do it with objects I suppose, but I've no doubt there'll be problems doing it. |
| ||
"or is the array handling in blitzmax too different?" Short answer: yes. If you describe exactly what it is you're trying to do, there might be alternative methods. |
| ||
in short, what i am trying to achieve is to copy a xml structure to a treeview, and use the treeview to draw objects from attributes in the xml. |
| ||
i got it working, but the code is nasty, i was thinking that if i could nail that recursive loop, i'd learn some ways of array handling that would clean up my code a bit... my code at the moment populating a level 5 array: TL.level[levelCnt].obj[objCnt].subObj1[subObj1Cnt].subObj2[subObj2Cnt].xObj = TL.level[levelCnt].obj[objCnt].subObj1[subObj1Cnt].subObj2[subObj2Cnt].xObj[..xObjCnt+1] TL.level[levelCnt].obj[objCnt].subObj1[subObj1Cnt].subObj2[subObj2Cnt].xObj[xObjCnt] = node ...please let me know if anyone has any alternative methods? |
| ||
funny enough Im doing something similar. Im not at my home PC right now so its from memory but in a nutshell I have all my data in a TMap a TMap has two parameters so the key is the field name and the value is the value stored as a string value OR another TMap. In the procedure to read the TMap Procedure processData(inData:TMap) it cycles through the keys in inData. For readkey:string = eachin inData.keys You can then see if the value if the key is another TMap. If TMap(getvaluefromkey(inData,readkey)) Then ' Call myself passing the TMap value processData(TMap(getvaluefromkey(inData,readkey))) Else print inkey + " = " + String(getvaluefromkey(inData,readkey) The actual code syntax is probably all wrong Im working from memory but thats roughly it. When I get time I was going to change it to just use some sort of TList as a stack so instead of recursive calling I push/pop my state using the stack. |
| ||
ah, the TMap returns. i had a feeling it would. Thanks for the TMap info, i think i get where you are going. will read up on hashtables and see if can understand better the difference between TLists and TMaps... |
| ||
umm, ok, if i can assume that a TMap works like a hash table, TMaps sounds like a better idea than TLists as they like arrays, use a direct lookup thereby being faster. is this correct, or am i completely off the rail here? |
| ||
I think It is much more efficient to implement complex tree structures (like xml structures) using your own object design. something like:Type MyNode Field Childs:TList = New TList Method AddChild(Node:MyNode) if node <> null then childs.addlast(Node) else throw "Null nodes are not allowed" endif End Method End Type Local Root:MyNode = New MyNode You can get all the nodes in the root. You can get any subnode of any node. the same as a tree control. Obviously you may have to implement the CountNodes, GetNodeAtIndex, RemoveNode, etc... but it should be very easy. |
| ||
mmhm, that is not too far from what i've got already... so many ways to achieve this - don't know which one to go for... my newbie head is also thinking of a single TList/TMap of types with parentID fields, so that i could retrieve data with matching parentID? sounds like an easy, but maybe not very efficient way.... for local node:myNode = eachin nodelist if (node.parentID = 20) print node.name endif next |
| ||
You will have to deal with some 'seek Id' 'comapre ID' etc for every node. why don't you think of nodes as real objects? I mean, store any child node in its parent node. you can do: Type MyNode Field Childs:TList = New TList Field Name:String Method AddNode:MyNode(Node:MyNode) if node <> null then childs.addlast(Node) return Node else throw "Null nodes are not allowed" endif End Method Method CountNodes:int() return Childs.Count() End Method Method NodeAtIndex:MyNode(index:int) return childs.valueAtIndex(index) End Method End Type 'Create the root node: Local Root:MyNode = New MyNode 'Create tree nodes in the root: Local AuxNode:MyNode AuxNode = New MyNode AuxNode.Name = "First Child Node" Root.AddNode(AuxNode) AuxNode = New MyNode AuxNode.Name = "Second Child Node" Root.AddNode(AuxNode) AuxNode = New MyNode AuxNode.Name = "Third Child Node" Root.AddNode(AuxNode) 'Now we add a subnode to the second node in the root. AuxNode = root.NodeAtIndex(1) 'We get the second node of the root (the first one is index 0) AuxNode.AddNode(New MyNode) 'We add it a child node AuxNode.NodeAtIndex(0).Name = "This is a subnode!" 'We set the child node a name this is a very fast and flexible way to create a complex tree. I haven't tested it, becouse I'm not at my computer now, so it can be buggy. |
| ||
I have a better example, it also produces recursive execution. This example generates a little cross-referencing issue, so be sure to call RemoveNode if you need to delete a node from its parent childs list. If you don't do this, the object will remain in memory, ignored by the GC |
| ||
putting a addNode method in the type, seems like a good idea - i think that will clean up my code a lot. and now if i can find a clever way to jump backwards as my recursive leafs are dying i think i am all set. maybe if i keep the level history in a array or something, i'll be able to jump from an outer leaf all the way back to root, hmmm |
| ||
ah, beautiful ziggy! i just saw your last post - recursive execution, that sounds like exactly what i need! thanks a lot ziggy, i have to rush off now, but i will have a look at your code in the morning, and see what i can make out of it - it looks very promising, thanks! |