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! |