Stumped on a recursive fuction in PHP

Injury

Lifer
Jul 19, 2004
13,066
2
81
So I'm working on a script for my BF2 Clan's website to display Ventrillo info and, long story short, I don't know how to set it up so it can search through an unknown nesting of channels.

as in... I can hard code it with nested loops to go through 3 levels, which is what we have, but if we decide to add more I'd rather use recursion to prevent having to re-code the thing.

Currently, the FIRST level of channels is hard coded, and beyond that it calls a function to find any nested channels.


Attached is a sample of the code to get the channels below the first set, but how to I make it reference itself without causing an endless loop?


$CID is "Channel ID"
$CHANS is an array with all the of the information about the channels
$chan is a count of the total channels

"PID" is "Parent ID", tells which CID to list a channel under.

Let me know if you need to see the arrays or anything

apparently the AT code function doesn't add carriage returns, sorry for the formatting.
 

tfinch2

Lifer
Feb 3, 2004
22,114
1
0
You need to have a base case in the recursive function to allow it a chance to stop calling itself.

Here is a simple example:

int factorial(int number) {
if(number <= 1)
return 1;
else
return number * factorial(number - 1);
}

The "if(number <= 1)" condition is the base case. It allows the function a way out of calling itself infinitely.
 

Injury

Lifer
Jul 19, 2004
13,066
2
81
One of the dilemmas is that when "for" loop starts , if the function within that calls itself it would reset the count of the variable in there and keep returning the same channel over and and over. Is there an way to maintain the previous count before it runs again when the loop calls itself? Or should I do it differently?

I thought maybe starting another array where the count is added to a list, and when each loop closes it knocks a number off of the end of the list... followed by the program reading in the last item on the list.
 

trexpesto

Golden Member
Jun 3, 2004
1,237
0
0
You need some kind of escape condition. It can be an error, null returned, or counting. Something that changes that you can check for.

My advice is to write it out in english, convert to pseudocode, and maybe it will become clearer. Looks like you are getting hung up on a bunch of old code.

$z < $chan;?

Also you have if-elses in that link that do the same thing in each case...

You and I both need to go back to school.



 

Injury

Lifer
Jul 19, 2004
13,066
2
81
Originally posted by: trexpesto
You need some kind of escape condition. It can be an error, null returned, or counting. Something that changes that you can check for.

My advice is to write it out in english, convert to pseudocode, and maybe it will become clearer. Looks like you are getting hung up on a bunch of old code.

$z < $chan;?

Also you have if-elses in that link that do the same thing in each case...

You and I both need to go back to school.

Heh... I'd be happy if I had the time and patience to go to school for it in the first place. Outside of correcting syntax for friends, this is probably the most difficult coding I've done. :p


I'm assuming I could get rid of most of the if statements with php's array functions, but I just flat out don't know how to do it.
 

drebo

Diamond Member
Feb 24, 2006
7,034
1
81
It would help somewhat if we knew what the structures of the $CHANS array and the various other variables you've got in there are, what they're supposed to be, and some sample data.

Also, I'm not sure exactly what you're trying to do. From what you describe, it could potentially be done with recursion, but I'm thinking that it might not be the best way to go about it.

Could you give us your raw data?
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
If you don't have a simple test case for the end of the loop, as tfinch suggested, then one approach is to use a stack-based algorithm. Here's an example in pseudo-code:

stack.push( root channel )
while ( chan = stack.pop() != nothing )
{
channelList.AddChannel(chan)
if ( chan.hasChannels )
{
foreach (subchan in chan.Channels)
push(subchan)
}
}

This can also be made recursive if needed.
 

trexpesto

Golden Member
Jun 3, 2004
1,237
0
0
To solve something like this, I thought hmm what would be a good model of the recursion, but would be fast and easy. In other words, what can I leverage to solve the problem without having ventrilo etc here.

I have IDLE, the Python editor, which is perfect because it's fast and the code is clean. Basically you want to traverse a tree, which files and folder would be a good model, but nested lists should be way easier and just as good.

So first I make some data, it will persist after I hit enter. It is a nested list where the lists are demarked by []
At the prompt:

dataList = [[1, 2, ['fee', 'fi', 'fo', ['fum']]], [3, 4], 5]

Then the function is defined to recurse thru the list (list used below is a python keyword:


def recur( aList ):

print "Recur: ", aList
for item in aList:

print "Item: ", item
if isinstance( item, list ) and len(item) > 0:

print ".........above item a non-empty list, so call recur() on it"
recur( item )


Then you can run the function on the data by entering:

recur(dataList)

and the output is:

Recur: [[1, 2, ['fee', 'fi', 'fo', ['fum']]], [3, 4], 5]
Item: [1, 2, ['fee', 'fi', 'fo', ['fum']]]
.........above item a non-empty list, so call recur() on it
Recur: [1, 2, ['fee', 'fi', 'fo', ['fum']]]
Item: 1
Item: 2
Item: ['fee', 'fi', 'fo', ['fum']]
.........above item a non-empty list, so call recur() on it
Recur: ['fee', 'fi', 'fo', ['fum']]
Item: fee
Item: fi
Item: fo
Item: ['fum']
.........above item a non-empty list, so call recur() on it
Recur: ['fum']
Item: fum
Item: [3, 4]
.........above item a non-empty list, so call recur() on it
Recur: [3, 4]
Item: 3
Item: 4
Item: 5



 

trexpesto

Golden Member
Jun 3, 2004
1,237
0
0
Trying to get some formatting to work, unsuccessfully

& nbsp; works as a space if you take out the space between ampersand and n

Then you can use a grip of them to get you there.
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
Speaking of formatting, I also noticed that you can use the nbsp tag to preserve indenting, to some extent.

The forum code pasting software has never worked right, as far as I know, but it occurs to me it wouldn't be hard to write a little app that lets you paste some code in one message box, and generate a version with the HTML needed to post it here on AT.

Or maybe a Greasemonkey script?

Maybe I'll take a look at that this weekend.
 

trexpesto

Golden Member
Jun 3, 2004
1,237
0
0
Originally posted by: Injury
I'm assuming I could get rid of most of the if statements with php's array functions, but I just flat out don't know how to do it.


I just mean that you have some code that does the same thing in both cases:

if ( $CLIENTS[$x][ADMIN] == "1"){
echo "" . $CLIENTS[$x][NAME];
} else {
echo "" . $CLIENTS[$x][NAME];
}


Which means you can shorten ( == speed up and clarify ) it to:

if ( $CLIENTS[$x][ADMIN] == "1"){
echo "" . $CLIENTS[$x][NAME];
}


And further down, same thing:

if ( $CHANS[$i][PROT] == "1"){
echo $CHANS[$i][NAME];
} else {
echo $CHANS[$i][NAME];
}


Your NBSPs got replaced with spaces in your code sorry.