Reputation: 1204
I am terribly stuck. I think I need to write a recursive method but I can't work out how...!
I am trying to convert an array of parent-child relationships into a hierarchical tree which I will later display to a user.
This is an example of the input data I might have:
$input = array(
array(
'itemGroupID' => 1,
'childItemGroupID' => 2
),
array(
'itemGroupID' => 1,
'childItemGroupID' => 3
),
array(
'itemGroupID' => 1,
'childItemGroupID' => 4
),
array(
'itemGroupID' => 1,
'childItemGroupID' => 212
),
array(
'itemGroupID' => 1,
'childItemGroupID' => 339
),
array(
'itemGroupID' => 1,
'childItemGroupID' => 336
),
array(
'itemGroupID' => 1,
'childItemGroupID' => 6
),
array(
'itemGroupID' => 1,
'childItemGroupID' => 5
),
array(
'itemGroupID' => 6,
'childItemGroupID' => 8
),
array(
'itemGroupID' => 6,
'childItemGroupID' => 9
),
array(
'itemGroupID' => 6,
'childItemGroupID' => 10
),
array(
'itemGroupID' => 6,
'childItemGroupID' => 11
),
array(
'itemGroupID' => 6,
'childItemGroupID' => 12
),
array(
'itemGroupID' => 6,
'childItemGroupID' => 13
),
array(
'itemGroupID' => 6,
'childItemGroupID' => 74
),
array(
'itemGroupID' => 9,
'childItemGroupID' => 15
),
array(
'itemGroupID' => 10,
'childItemGroupID' => 16
),
array(
'itemGroupID' => 11,
'childItemGroupID' => 17
),
array(
'itemGroupID' => 12,
'childItemGroupID' => 18
),
array(
'itemGroupID' => 13,
'childItemGroupID' => 19
),
array(
'itemGroupID' => 74,
'childItemGroupID' => 75
)
);
I wish to get back data in a format like:
$output = array(
array(
'itemGroupID' => 1,
'children' => array(
array(
'itemGroupID' => 2
),
array(
'itemGroupID' => 3
),
array(
'itemGroupID' => 4
),
array(
'itemGroupID' => 212
),
array(
'itemGroupID' => 339
),
array(
'itemGroupID' => 336
),
array(
'itemGroupID' => 6,
'children' => array(
array(
'itemGroupID' => 8
),
array(
'itemGroupID' => 9,
'children' => array(
array(
'itemGroupID' => 15
)
)
),
array(
'itemGroupID' => 10,
'children' => array(
array(
'itemGroupID' => 16
)
)
),
array(
'itemGroupID' => 11,
'children' => array(
array(
'itemGroupID' => 17
)
)
),
array(
'itemGroupID' => 12,
'children' => array(
array(
'itemGroupID' => 18
)
)
),
array(
'itemGroupID' => 13,
'children' => array(
array(
'itemGroupID' => 19
)
)
),
array(
'itemGroupID' => 74,
'children' => array(
array(
'itemGroupID' => 75
)
)
)
)
),
array(
'itemGroupID' => 5
)
)
)
);
I managed to write some code which would tell me the root(s) to start from. (As I was worried that if you were recursing from the first node it might turn out that this is from half-way down the chain already...)
Btw, the element I output can be used to get the starting index, for each hierarchical chain.
private function _arraySearch($arr, $callback)
{
foreach ($arr as $key => $item) {
if ($callback($item)) {
return $key;
}
}
return false;
}
private function _findRootsOfItemGroupTree($activeItemGroupChildren)
{
$searchArray = $activeItemGroupChildren;
$roots = array();
foreach ($activeItemGroupChildren as $itemGroupChild) {
$parentItemGroupID = $itemGroupChild['itemGroupID'];
$found = array_filter($searchArray, function ($element) use ($parentItemGroupID) {
return $element['childItemGroupID'] == $parentItemGroupID;
});
$rootItemGroupID = $parentItemGroupID;
if (count($found) == 0
&& $this->_arraySearch($roots,
function ($element) use ($rootItemGroupID) {
return $element['itemGroupID'] == $rootItemGroupID;
}) === false) {
$roots[] = $itemGroupChild;
}
}
return $roots;
}
However, I now need to use this information to create a new associative array. I can't work out how. (I will post some workings in a couple of minutes..)
Ideas?
note: assume there are no recursive loops in this structure even though they could technically exist.
Upvotes: 3
Views: 766
Reputation: 1608
If I understand your problem correctly, this should work.
Notice how I call the orderMe
function inside the function to make it recursive.
function orderMe($input, $parentId)
{
$return = array($parentId => array('itemGroupID' => $parentId));
$childs = array();
foreach ($input as $i)
{
if ($i['itemGroupID'] == $parentId)
{
$return[$i['itemGroupID']]['children'][$i['childItemGroupID']] = array('itemGroupID' => $i['childItemGroupID']);
$childs[] = $i['childItemGroupID'];
}
if (in_array($i['childItemGroupID'], $childs))
{
$allChilds = orderMe($input, $i['childItemGroupID']);
if (!empty($allChilds[$i['childItemGroupID']]['children']))
$return[$i['itemGroupID']]['children'][$i['childItemGroupID']] = $allChilds;
}
}
return $return;
}
print_r(orderMe($input, 1));
Outputs:
array (
1 =>
array (
'itemGroupID' => 1,
'children' =>
array (
2 =>
array (
'itemGroupID' => 2,
),
3 =>
array (
'itemGroupID' => 3,
),
4 =>
array (
'itemGroupID' => 4,
),
212 =>
array (
'itemGroupID' => 212,
),
339 =>
array (
'itemGroupID' => 339,
),
336 =>
array (
'itemGroupID' => 336,
),
6 =>
array (
6 =>
array (
'itemGroupID' => 6,
'children' =>
array (
8 =>
array (
'itemGroupID' => 8,
),
9 =>
array (
9 =>
array (
'itemGroupID' => 9,
'children' =>
array (
15 =>
array (
'itemGroupID' => 15,
),
),
),
),
10 =>
array (
10 =>
array (
'itemGroupID' => 10,
'children' =>
array (
16 =>
array (
'itemGroupID' => 16,
),
),
),
),
11 =>
array (
11 =>
array (
'itemGroupID' => 11,
'children' =>
array (
17 =>
array (
'itemGroupID' => 17,
),
),
),
),
12 =>
array (
12 =>
array (
'itemGroupID' => 12,
'children' =>
array (
18 =>
array (
'itemGroupID' => 18,
),
),
),
),
13 =>
array (
13 =>
array (
'itemGroupID' => 13,
'children' =>
array (
19 =>
array (
'itemGroupID' => 19,
),
),
),
),
74 =>
array (
74 =>
array (
'itemGroupID' => 74,
'children' =>
array (
75 =>
array (
'itemGroupID' => 75,
),
),
),
),
),
),
),
5 =>
array (
'itemGroupID' => 5,
),
),
),
)
Upvotes: 3