'PHP logic to build multi level tree
Updated
I have the following array, for example:
[{id:1},{id:2}{id:3},{id:4},{id:5},...{id:20}]
May I ask how to generate a JSON object as below in order to achieve the following tree in Image 1? It does not need a parent id as it is first come first serve and each node will only have direct 3 childs.
I think it will run through a function and append the children to the object. Also I wish to control the number of childrens in the future too. Thanks in advance
JSON object
{
"tree": {
"id": 1,
"children": [
{
"id": 2,
"children": [
{
"id": 5,
"children": [
{
"id": 11
},
{
"id": 12
},
{
"id": 13
}
]
},
{
"id": 6
},
{
"id": 7
}
]
},
{
"id": 3,
"children": [
{
"id": 8
},
{
"id": 9
},
{
"id": 10
}
]
},
{
"id": 4,
"children": [
{
"id": 11
},
{
"id": 12
},
{
"id": 13
}
]
}
]
}
}
Image 1: the tree illustration
Solution 1:[1]
First of all your JSON object contains duplicate id's.
So the logic is - take first element, mark it as a current_parent. Every subsequent element is placed into a parents_queue and placed into a current_parent children array. If current_parent children array is 3 elements length, take the next node from parents_queue and mark it as a current_parent. Sample code:
// Generate test data
$data = [];
foreach(range(1,20) as $i)
$data[] = ['id' => $i];
// Tree root and helper vars
$root = null;
$current_parent_node_pointer = null;
$parents_queue = [];
for( $i = 0; $i < count($data); $i++ ){
$node = &$data[$i];
// Not the first element
if( $i ){
if( empty( $current_parent_node_pointer['children'] ) )
$current_parent_node_pointer['children'] = [];
// Add the node to current parent
$current_parent_node_pointer['children'][] = &$node;
// Current parent has 3 children now, take a new one from the queue;
if( count( $current_parent_node_pointer['children'] ) == 3 ){
unset($current_parent_node_pointer); // destroy the reference before assining a new value
$current_parent_node_pointer = &$parents_queue[0];
array_shift($parents_queue); // remove current parent from the queue
}
// Add current node to the parents queue
$parents_queue[] = &$node;
}
// First element; actually an initialization
else {
$root = &$node;
$current_parent_node_pointer = &$node;
}
}
$json = json_encode( ['tree' => $root] );
UPD: if your input is an array of objects, code becomes slightly simpler (no reference usage needed):
// Generate test data
$data = [];
foreach(range(1,20) as $i)
$data[] = (object)['id' => $i];
// Tree root and helper vars
$root = null;
$current_parent_node_pointer = null;
$parents_queue = [];
foreach($data as $node){
// Not the first element
if( !empty($current_parent_node_pointer) ){
if( empty( $current_parent_node_pointer->children ) )
$current_parent_node_pointer->children = [];
// Add the node to current parent
$current_parent_node_pointer->children[] = $node;
// Current parent has 3 children now, take a new one from the queue;
if( count( $current_parent_node_pointer->children ) == 3 )
$current_parent_node_pointer = array_shift($parents_queue);
// Add current node to the parents queue
$parents_queue[] = $node;
}
// First element; actually an initialization
else {
$root = $node;
$current_parent_node_pointer = $node;
}
}
$json = json_encode( ['tree' => $root] );
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |

