Link to home
Create AccountLog in
Avatar of usslindstrom
usslindstromFlag for Japan

asked on

VBSript recursion in function

Experts, if possible can I get a little nudge on a recursion item within vbscript?

I have a function that I need to call on itself to cycle through some data.

Without overloading anyone with too much info, I basically have a dictionary object, that is laid out like so:

Dictionary Key = Parent Object
Dictionary Value = Children, each separated by "\\"


arrNavChildren = fncGatherNavChildren(strNavKey, dicRelationshipParentToChild.Item(strNavKey))

Function fncGatherNavChildren(strNavKey, strNavItem)
   If dicRelationshipParentToChild.Exists(strNavKey) Then
      fncGatherNavChildren = Split(strNavItem, "\\")
   Else
      fncGatherNavChildren = ""
   End If
End Function

Open in new window


Basically, I need to see about having the function call itself on each pass, to see if there are more children to add to the array.  *If that makes sense.



So, it could be like this:

ParentA, ChildA\\ChildB\\ChildC
ChildB, SubChildA\\SubChildB...  and so on.

Would somebody happen to know where I can find information on how to accomplish this?  The Google Zhar hasn't been too helpful as of yet.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

Are you sure you have your data set up correctly?  

Beer = rating
key("Heady Topper")="4.7"
key("Pliny The Younger")="4.65"
key("Zombie Dust")="4.61"

Are you saying you want to look up "Zombie Dust", find the rating of 4.61, then find all other beers that have 4.61 rating?
Avatar of usslindstrom

ASKER

Yeah - basically.  I know it sounds weird - but let me see if I can elaborate.

In the structure I posted above, let's expand it and add more data:


ParentA, ChildA\\ChildB\\ChildC
ParentB, ChildD\\ChildE\\ChildF
ParentC, ChildG
ParentD, ChildH\\ChildI

So, using this method, it's easy for me to grab any of these "parents" child objects.  But, the Child objects can also be parents in my data structure...

ChildA, *NO_CHILDREN*
ChildB, SubChildA\\SubChildB
ChildC, SubChildC\\SubChildD\\SubChildE
ChildD, *NO_CHILDREN*
ChildE, *NO_CHILDREN*
ChildF, SubChildF

And this process could repeat itself indefinately...

SubChildA, *NO_CHILDREN*
SubChildB, SubSubChildA\\SubSubChildB
etc.


In a tree view, the above data would be layed out like so:
    ParentA
        ChildA
        ChildB
            SubChildA
            SubChildB
                SubSubChildA
                SubSubChildB
        ChildC
            SubChildC
            SubChildD
            SubChildE
    ParentB
        ChildD
        ChildE
        ChildF
            SubChildF
    ParentC
        ChildG
    ParentD
        ChildH
        ChildI

*If this makes sense.
>And this process could repeat itself indefinitely...

and that gets you to an endless loop.  If that is the case, there is something wrong in how you set up your data.


Below assumes you have a dictionary object with key "ParentA" that contains "ChildA\\ChildB\\ChildC"

When you look up the key, "ParentA" it will convert the result item to a new array, then loop through and check to see if there are more children.  If so, it will add to the array

'ParentA, ChildA\\ChildB\\ChildC
'ParentB, ChildD\\ChildE\\ChildF
'ParentC, ChildG
'ParentD, ChildH\\ChildI

dim MyDictionary
Set MyDictionary=Server.CreateObject("Scripting.Dictionary")
MyDictionary.Add "ParentA","ChildA\\ChildB\\ChildC"
MyDictionary.Add "ParentB", "ChildD\\ChildE\\ChildF"
MyDictionary.Add "ParentC", "ChildG"
MyDictionary.Add "ParentD", "ChildH\\ChildI"

'create the holding variable
dim newString, temp
newString=""


dim strP="ParentA,ParentB,ParentC,ParentD"
arrP=split(strP,",")
for each parent in arrP  
temp=""
childtemp=""
   if MyDictionary.Exists(parent)= true then ' check to see if ParentA exists.
        temp=MyDictionary.item(parent)
        newString=newString&temp&","
        arrTemp=split(temp,"\\") 'create an array from ChildA\\ChildB\\ChildC"
        for each child in arrTemp
            if MyDictionary.Exists(child)= true then
                newString=newString&MyDictionary.item(child)&","
            end if
        next
   end if
next
' now we end up with a comma at the end of our string and we need to take it out
newString=left(newString,len(newString)-1)

Open in new window

If you think you need an endless loop, then we should look at your data structure because that does not sound right.
Please bear with me, I'm going over everything you're trying to show me.  *Thanks for the assist btw.

- Looking at the  logic of your example, I'm reading into it, that it would only perform 2 levels of parent --> child relationship passes.

It would grab the dictionary defined "parent" node, and pass through, up to the "ChildX" ones, but nothing in the "subChildX" tree, because it wasn't coded in.

I was hoping there would just be a quick function that I could throw together, that would per-say allow me to have "ParentA" defined, then it run through the data and give me the tree output of every child object.  (i.e.  ParentA is defined in the dictionary, and has ChildA,B,&C., Child A also has children objects of E,D,&F)

ParentA
    ChildA
        SubChildE
        SubChildD
        SubChildF
    ChildB
    ChildC
etc.

I was thinking it could be a simple function that would basically return the data values I have.  Meaning, I query ParentA, it returns \\ChildA,B,&C.  Run through the array of the returned values, and check if any of them are parents as well.  Continue this cycle until there aren't any more matches.
SOLUTION
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Wow! - Thanks.  Give me a minute to read through what you're showing me, so I can understand it...
Avatar of Bill Prew
Bill Prew

Can't resist taking a shot at this, but just coming up to speed.

Just curious, how do you populate the data? Any reason a delimiter string was used for the "array" of children? Rather than say an array, or another dictionary object (yes, you can nest objects).

~bp
It will be nice to see another version...
It's data from AD.

I actually have 2 dictionary objects currently, and I've been trying to get it working with multiple attempts at storing the data.

I'm making a HTA template that rolls through AD and provides some lookups based on clicking an object.  I set the ID in the HTA to the DN of the object I just clicked, and so far it's great.  The original draft had me using two separate list boxes, which is all fine...  Except I wanted to convert it to using expansive and contracting unordered lists (<ul>) using a mix of js.

I've got it almost entirely worked out, but got hung up with what you guys are assisting me on.

//-----------------------------------

In my original build my structure was as follows:

DictionaryObject
Key = AD DN of object
Value = Re-hashed output of the tree path (I.E. DOMAIN\OU\OU\OU)

This method worked fairly well, as I could sort the dictionary based on the value, and it gave me a great ordered list.

My second attempt, is where I'm at right now.  I have two dictionary objects, one of the base tree that contains the root domains, and from there it branches out into filling in the 2nd dictionary.  I was adding the "\\" as I knew I could just split on those chars together, and I was under the idea that it would be easier than it is.

As you can tell, I may be tackling this wrong, and there's probably a better way to store the data.  And you bring up a good point BP, with the value of the dictionary object just being an array.

I'd imagine I'd still be where I'm at, with the need for a function to call itself.  I think I see where Padas was showing me to go, but I still don't quite get it yet.
ASKER CERTIFIED SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Sorry for the late reply here guys.  I've been knee deep in masaging the script to get it working correctly in my instance...

I ended up using BP's example (but thanks to both of you for supplying me a direction to start heading).  Ultimately, in order to pull it off in my environment, I ended up with a few dictionary objects:

1.  The nav tree that contains all items from AD
2.  A relationship that has one-->many (Parent --> Child)
3.  A relationship that has one-->one (Child --> Parent)
4.  A duplicate check (If .Exists) as it gets added to the HTML code
5.  BP's example, that I used to throw the navObject & subLevel (int = int +1 loop) to see where I was in the tree.

Using a mixture of ALL of the above dictionaries, I now have a working HTA that has a point-click navigation tree of AD.  Where you click on an OU, and all the sub OUs get added as nested <ul>'s to each node.  It's probably pretty sloppy - but it works.

Thanks for the nudge guys, you both make EE a great place to come back and collaborate on.
Here's a copy, if anyone's interested.  *Ignore the layout, that'll come later.

I had to rename the following files in order to upload it to EE:

.hta --> .txt    
     .\AD_GUI.hta

.vbs --> .txt
     .\Scripts\AD\*.vbs
     .\Scripts\DataManip\*.vbs
     .\Scripts\Global\*.vbs
     .\Scripts\HTMLOutput\*.vbs
     .\Scripts\Init\*.vbs

.js --> .txt
     .\Scripts\CreateTree\*.js

.\Scripts\TxtAssist\TxtAssist.vbs --> TxtAssist.txt
.\Scripts\TxtAssist\TxtAssist.cfg --> TxtAssist_cfg.txt
AD-GUI.zip