Home > OS >  Find a key in a multi level array and gel all childrens belonging to it in php
Find a key in a multi level array and gel all childrens belonging to it in php

Time:10-12

I have a bunch of name-parentname pairs, that I turned into a heirarchical tree structure. So for example, these are my pairings:

Child : Parent
H : G
F : G
G : D
E : D
A : E
B : C
C : E
D : 0

Which after using this function found here.

$array = array('H' => 'G', 'F' => 'G', ..., 'D' => null);
function to_tree($array)
{
    $flat = array();
    $tree = array();

    foreach ($array as $child => $parent) {
        if (!isset($flat[$child])) {
            $flat[$child] = array();
        }
        if (!empty($parent)) {
            $flat[$parent][$child] =& $flat[$child];
        } else {
            $tree[$child] =& $flat[$child];
        }
    }

    return $tree;
}

$array_tree = to_tree($array)

I get an array like this:

Array
(
    [7] => Array
        (
            [24] => Array
                (
                )

            [38] => Array
                (
                )

            [78] => Array
                (
                )

            [103] => Array
                (
                )

            [121] => Array
                (
                )

            [163] => Array
                (
                    [162] => Array
                        (
                        )

                    [213] => Array
                        (
                        )

                    [214] => Array
                        (
                        )

                    [215] => Array
                        (
                        )

                )
      ...

What I need is to get an array of the key i'm looking for plus all the children keys. Let's say I'm looking for key 7, so I would get an array like this one:

Array
(
    [0] => 7
    [1] => 24
    [2] => 38
    [3] => 78
    [4] => 103
    [5] => 121
    [6] => 163
    [7] => 162
    [8] => 213
    [9] => 214
    [10] => 215
    ...
)

But I also need to look on keys like 163 and get:

Array
(
    [0] => 163
    [1] => 162
    [2] => 213
    [3] => 214
    [4] => 215
)

I think is not that hard for experienced users, but I can't quite figure it out.

CodePudding user response:

<?php

    $data = array(
        'H' => 'G',
        'F' => 'G',
        'G' => 'D',
        'E' => 'D',
        'A' => 'E',
        'B' => 'C',
        'C' => 'E',
        'D' => '0'
    );

    $root_node = 'G'; // Change the root node here.

    $parents_with_children = array();

    // 1) First create a data structure with parents and children.
    foreach($data as $child => $parent){
        if(!isset($parents_with_children[$parent])){
            $parents_with_children[$parent] = array();
        }
        $parents_with_children[$parent][] = $child;
    }

    // 2) Then call a recursive function to find the tree structure, from a specific root node
    find_children($root_node, $parents_with_children);

    function find_children($root_node, $parents_with_children){
        echo '<br>Parent:'.$root_node;
        $found_children = array();
        foreach($parents_with_children as $parent => $children){
            if($parent === $root_node){
                foreach($children as $child){
                    if(!in_array($child, $found_children)){
                        echo '<br>- Child:'.$child;
                        $found_children[] = $child;
                    }
                }
            }
        }

        foreach($found_children as $child){
            find_children($child, $parents_with_children);
        }
    } // find_children

?>

CodePudding user response:

After digging a lot I came up with this solution:

function get_children($needle, array $haystack, array &$result = null, $found = false) {
    // This is to initialize the result array and is only needed for
    // the first call of this function
    if (is_null($result)) {
        $result = [];
    }
    foreach ($haystack as $key => $value) {
        // Check whether the key is the value we are looking for. If the value
        // is not an array, add it to the result array.
        if ($key === $needle && empty($value)) {
            //key found but has no children, so lets add the key to the result.
            $result[] = $key;
        }
        elseif ($key === $needle && !empty($value)) {
            // key found and it has children so let's find all the children.
            $result[] = $key;
            get_children(null, $value, $result, true);
        }
        elseif ($found && empty($value)) {
            // If key found then we add the children.
            $result[] = $key;
        }
        elseif ($found && !empty($value)) {
            // If key found but children has more children then were looking for them.
            $result[] = $key;
            get_children(null, $value, $result, true);
        }
        elseif (!empty($value)) {
            // If we haven't found the key, we keep looking through subarrays.
            get_children($needle, $value, $result, false);
        }
    }
    return $result;
}

This is working great, I don't know if it's the best solution.

  • Related