Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: Return an array from recursive function

Tags:

php

recursion

I have an array like this one:

SimpleXMLElement Object
(
    [BrowseNodes] => SimpleXMLElement Object
        (
            [BrowseNode] => SimpleXMLElement Object
                (
                    [BrowseNodeId] => 969391031
                    [Name] => Bambine e ragazze
                    [Children] => SimpleXMLElement Object
                        (
                            [BrowseNode] => Array
                                (
                                    [0] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 969394031
                                            [Name] => Calze
                                        )

                                    [1] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 3635837031
                                            [Name] => Felpe
                                        )

                                    [2] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 3635838031
                                            [Name] => Giacche
                                        )

                                    [3] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 3635839031
                                            [Name] => Guanti da giocatore
                                        )

                                    [4] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 969392031
                                            [Name] => Maglie
                                        )

                                    [5] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 4351854031
                                            [Name] => Maglie per tifosi
                                        )

                                    [6] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 3635840031
                                            [Name] => Magliette da portiere
                                        )

                                    [7] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 969393031
                                            [Name] => Pantaloncini
                                        )

                                    [8] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 3635841031
                                            [Name] => Pantaloncini da portiere
                                        )

                                    [9] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 3635842031
                                            [Name] => Pantaloni
                                        )

                                    [10] => SimpleXMLElement Object
                                        (
                                            [BrowseNodeId] => 3635843031
                                            [Name] => Tute da ginnastica
                                        )

                                )

                        )

                    [Ancestors] => SimpleXMLElement Object
                        (
                            [BrowseNode] => SimpleXMLElement Object
                                (
                                    [BrowseNodeId] => 969386031
                                    [Name] => Abbigliamento
                                    [Ancestors] => SimpleXMLElement Object
                                        (
                                            [BrowseNode] => SimpleXMLElement Object
                                                (
                                                    [BrowseNodeId] => 937258031
                                                    [Name] => Calcio
                                                    [Ancestors] => SimpleXMLElement Object
                                                        (
                                                            [BrowseNode] => SimpleXMLElement Object
                                                                (
                                                                    [BrowseNodeId] => 524013031
                                                                    [Name] => Categorie
                                                                    [IsCategoryRoot] => 1
                                                                    [Ancestors] => SimpleXMLElement Object
                                                                        (
                                                                            [BrowseNode] => SimpleXMLElement Object
                                                                                (
                                                                                    [BrowseNodeId] => 524012031
                                                                                    [Name] => Sport e tempo libero
                                                                                )

                                                                        )

                                                                )

                                                        )

                                                )

                                        )

                                )

                        )

                )

        )

)

What I need to do is to build a breadcrumb using Anchestors. The one that is at the end of the list should be the first one. So, as an example:

Sport e tempo libero > Categorie > calcio...

I'm trying to iterate the xml with a function in this way without success:

    $rec=$result->BrowseNodes->BrowseNode->Ancestors->BrowseNode;

    $bread=array();
    function recursive($r)
    {
        do{
            $bread[]=$r->BrowseNodeId;
            recursive($r->Ancestors->BrowseNode);
        }while(isset($r->Ancestors));
        $bread=array_reverse($bread);
        return $bread;
    }

    print_r(recursive($rec));

I found something similar on stackoverflow but no suggestions helped me to sort this out.

like image 522
Luca Avatar asked Dec 09 '16 17:12

Luca


People also ask

How can I return an array from a function in PHP?

php function dofoo() { $array["a"] = "Foo"; $array["b"] = "Bar"; $array["c"] = "Baz"; return $array; } $foo = dofoo(); ?> Without returning an array, the only other way to pass data back to the calling script is by accepting parameters by reference and changing them inside the function.

How do you return an array from a recursive function in Java?

Method 1(Using Recursion) : Create a recursive function say, largest_element (int n, int arr[]). Base Condition : If(n==1) return arr[0]. ( If the remaining array is of length 1, return the only present element i.e. arr[0] ) Else, return max(arr[n-1], largest_element(n-1, arr))

Can recursive methods return a value?

Recursion is a method of programming or coding a problem, in which a function calls itself one or more times in its body. Usually, it is returning the return value of this function call. If a function definition satisfies the condition of recursion, we call this function a recursive function.

Does recursion use stack or heap?

Memory Allocation in Recursion. When a function is called, its memory is allocated on a stack.


2 Answers

To create a recursive function with an output, you need three things:

  1. A variable or a parameter to hold the current position, which is $r in your code. You got this one right.
  2. A variable or a parameter that holds the result, which you don't have. At first it appears to be $bread, but it is not holding any value because it is empty every time you call recursive(). A simple solution is to declare it as global inside the function.
  3. An if statement that checks the stop condition, which you don't have. Instead, you have a do-while loop in your code.

So, you have two mistakes there. Based on your code and modifying it as little as possible, this is the correct code:

$rec = $result->BrowseNodes->BrowseNode->Ancestors->BrowseNode;

$bread = array();
function recursive($r)
{
    global $bread;

    $bread[] = strval($r->BrowseNodeId);

    if(isset($r->Ancestors)){
        return recursive($r->Ancestors->BrowseNode);
    }else{
        return array_reverse($bread);
    }
}

print_r(recursive($rec));

There you go.

Update: I agree with @FlameStorm, global should be avoided if possible. I also received suggestion to use static instead, but it introduces a bug. Thus, I recommend avoiding static as well if you're not sure how to use it.

This is the improved code:

$rec = $result->BrowseNodes->BrowseNode->Ancestors->BrowseNode;

function recursive($r)
{
    if(isset($r->Ancestors))
        $bread = recursive($r->Ancestors->BrowseNode);

    $bread[] = strval($r->BrowseNodeId);
    return $bread;
}

print_r(recursive($rec));

The $bread variable outside the function is no longer needed. Also, neither global or static is used.

like image 168
Rei Avatar answered Oct 12 '22 23:10

Rei


SimpleXMLElement is not an array. You could convert it to an array, but PHP offers an iterator specifically for this case, SimpleXMLIterator.

Since you have a recursive structure, my suggestion is to flatten it with RecursiveIteratorIterator. Assuming your data is in a variable called $xml, your solution might look something like this:

$xmlIterator  = new SimpleXMLIterator($xml->Ancestors);
$flatIterator = new RecursiveIteratorIterator($xmlIterator, RecursiveIteratorIterator::SELF_FIRST);

$breadcrumb = [];
foreach($flatIterator as $node) {
    $breadcrumb[] = $node['Name'];
}

$breadcrumb = array_reverse($breadcrumb);
like image 36
quickshiftin Avatar answered Oct 12 '22 22:10

quickshiftin