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.