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