I have a tree of categories of the following structure:

[6] => Array
    (
        [id] => 6
        [name] => computers
        [productCount] => 0
        [children] => Array
            (
                [91] => Array
                    (
                        [id] => 91
                        [name] => notebook
                        [productCount] => 5
                        [children] => Array
                            (
                            )
                    )

                [86] => Array
                    (
                        [id] => 86
                        [name] => desktop
                        [productCount] => 0
                        [children] => Array
                            (
                            )
                    )
            )
    )

Beside a subcategory, each category may contain products (like a folder may contain subfolders and just files).

I'm trying to write a recursive function which I want to take this array as reference and strip both leaf categories with [productCount] = 0 and all parent categories that contain such empty nodes. In other words, after processing I want to have only those categories that hold products on any sublevels.

I've wrote some code, now debugging it and it doesn't strip empty nodes. May be I'm not using references properly. Please, help me fix it, if possible.

    function pruneTree( & $node) {
    if ( ! $node['children'] && ! $node['productCount']) {
        unset($node);
    }
    if ( ! empty($node['children'])) {
        foreach ($node['children'] as $key => $child) {
            pruneTree($node['children'][$key]);
        }
    }
    return;
}

Comments

Is array() == false ?

Written by Ghommey

@Ghommey: Yes, in PHP an empty array is considered falsy.

Written by BoltClock

Accepted Answer

You could also change the parameter in the function to take an array of nodes instead of a single node. This changes the recursion slightly, and prevents the need to pass along a key:

function pruneTree(&$nodes) {
    foreach ($nodes as $key => $node) {
        if (!$node['children'] && !$node['productCount']) {
            unset($nodes[$key]);
        } elseif (!empty($node['children'])) {
            pruneTree($nodes[$key]['children']);
            // This line checks if all the children have been pruned away:
            if (empty($nodes[$key]['children'])) {
                unset($nodes[$key]);
            }
        }
    }
}

Also, added a check that ensures that if all child nodes are pruned, the parent (now, leaf) node also gets pruned.

Hope this helps!


Test data:

$data = array(
    6 => array(
        'id' => 6,
        'name' => 'computers',
        'productCount' => 0,
        'children' => array(
            91 => array(
                'id' => 91,
                'name' => 'notebook',
                'productCount' => 5,
                'children' => array()
            ),
            86 => array(
                'id' => 86,
                'name' => 'desktop',
                'productCount' => 0,
                'children' => array()
            )
        )
    )
);

The Call:

pruneTree($data);
echo '<pre>';
print_r($data);
echo '</pre>';
Written by RabidFire
This page was build to provide you fast access to the question and the direct accepted answer.
The content is written by members of the stackoverflow.com community.
It is licensed under cc-wiki