tags:

views:

198

answers:

1

I'm writing a text tag parser and I'm currently using this recursive method to create tags of n words. Is there a way that it can be done non-recursively or at least be optimized? Assume that $this->dataArray could be a very large array.

/**
 * A recursive function to add phrases to the tagTracker array
 * @param string $data
 * @param int $currentIndex
 * @param int $depth
 */ 
protected function compilePhrase($data, $currentIndex, $depth){
    if (!empty($data)){
        if ($depth >= $this->phraseStart){
            $this->addDataCount($data, $depth);
        }
        if ($depth < $this->phraseDepth){
            $currentIndex = $currentIndex + 1;
            //$this->dataArray is an array containing all words in the text
            $data .= ' '.$this->dataArray[$currentIndex]; 
            $depth += 1;
            $this->compilePhrase($data, $currentIndex, $depth);
        }
    }
}
+2  A: 

See if you can use tail recursion rather than call-based recursion. Some rewriting may be required but a cursory looks says it is fine to do.

Tail recursion is great for a subset of recursive functions, and good practice to spot when loops can replace recursion, and how to rewrite.

Saying that, I don't know what the overhead inside PHP is of the call. Might just be one return-pointer type setup rather than a real stack wind.

Turns out about the same. Does PHP optimize tail recursive calls out itself?

Here is my rewrite, but beware, my brain is currently sleep deprived!

protected function compilePhrase($data, $currentIndex, $depth){
    /* Loop until break condition */
    while(true) {
        if (!empty($data)){
            if ($depth >= $this->phraseStart){
                $this->addDataCount($data, $depth);
            }
            if ($depth < $this->phraseDepth){
                $currentIndex = $currentIndex + 1;
                // A test here might be better than the !empty($data)
                // in the IF condition. Check array bounds, assuming
                // array is not threaded or anything
                $data .= ' '.$this->dataArray[$currentIndex]; 
                $depth += 1;
            }else{
               break;
            }
        }else{
           break;
        }
    }
    /* Finish up here */
    return($this->dataArray);
}
Aiden Bell
Hmm. It works if you add an else/break for the second nested if statement. However, it seems to average about the same speed as the recursive function.
VirtuosiMedia
Cool, will edit.
Aiden Bell
Tail recursion isn't generally considered a speed optimization (though unwinding the stack does take time, it should be small compared to all of the string concatenation that's going on). It's a space optimization to prevent you from overflowing the stack.
Ken Bloom
@Ken How would you speed up the string concatenation?
VirtuosiMedia
@Ken - Good point. Though I didn't answer from a speed perspective ;)
Aiden Bell