I guess my brain starts to slow down, but I want to get a recursive array of my results from this table :
|id|int(11)|
|name|varchar(150)|
|type|tinyint(4)|
|id_parent|mediumint(9)|
|1|Marque forte|1|0|
|2|Communication|2|1|
|3|Respect du CI|0|2|
|4|Stratégie digitale|0|2
|5|Expérience de marque|2|1|
|6|Gastronomie|0|5|
I want an array like :
array('id' => array('name' => $name, 'childs' => array( ... ), 'id' => ...)
I just want to order my dataset in one array.
I tried this so far :
// returns array of objects - codeigniter result
$dbResult = $this->db->get_where('table')->result();
// will contains the array
$this->data['tree'] = array();
$this->getRecursive(0, 0, $dbResult);
....
private function getRecursive($parent, $niveau, $result)
{
foreach ($result AS $row)
{
if ($parent == $row->id_parent)
{
$this->data['tree'][] = array($row->name => $this->getRecursive($row->id, ($niveau + 1), $result));
}
}
}
Which gives me weird result ...
Please try this. I have used the $source array for testing. Since I did not get my result set from an actual database, you will have to make some changes in order to adjust it with your code (eg. change $row['id_parent'] to $row->id_parent and so on). However, conceptually it should work.
<?php
$source = [
['name' => 'A', 'id' => 1, 'id_parent' => 0],
['name' => 'B', 'id' => 2, 'id_parent' => 1],
['name' => 'C', 'id' => 3, 'id_parent' => 1],
['name' => 'D', 'id' => 4, 'id_parent' => 2],
['name' => 'E', 'id' => 5, 'id_parent' => 3],
['name' => 'F', 'id' => 5, 'id_parent' => 0],
];
function getRecursive($source, $parent) {
$result = [];
foreach ($source as $row) {
if ($parent == $row['id_parent']) {
$result[] = [
'id' => $row['id'],
'name' => $row['name'],
'childs' => getRecursive($source, $row['id'] )
];
}
}
return $result;
}
print_r(getRecursive($source, 0));
You don't need a recursion here - the following should do the job
$arrTreeById = [];
//$arrData = $this->db->get_where('table')->result_array();
$arrData = [
[
'id' => 1,
'name' => 'Marque forte',
'type' => 2,
'id_parent' => 0
],
[
'id' => 2,
'name' => 'Communication',
'type' => 2,
'id_parent' => 1
],
[
'id' => 3,
'name' => 'Respect du CI',
'type' => 0,
'id_parent' => 2
],
[
'id' => 4,
'name' => 'Stratégie digitale',
'type' => 0,
'id_parent' => 2
],
[
'id' => 5,
'name' => 'Expérience de marque',
'type' => 2,
'id_parent' => 1
],
[
'id' => 6,
'name' => 'Gastronomie',
'type' => 0,
'id_parent' => 5
],
];
foreach($arrData AS $arrItem)
{
$arrTreeById[$arrItem['id']] = $arrItem;
}
foreach($arrTreeById AS &$arrItem)
{
if (isset($arrTreeById[$arrItem['id_parent']]))
{
$arrTreeById[$arrItem['id_parent']]['arrChilds'][] = &$arrItem;
}
if ($arrItem['id_parent'] == 0) $intStartingKey = $arrItem['id'];
}
print_r($arrTreeById[$intStartingKey]);
Related
I have PHP array (tree), something like this:
$categoryTree = [
0 => [
'id' => 1360,
'parent' => 0,
'name' => 'main A',
'children' => [
0 => [
'id' => 1361,
'parent' => 1360,
'name' => 'sub a1'
],
1 => [
'id' => 57,
'parent' => 1360,
'name' => 'sub a2'
]
]
],
1 => [
'id' => 10,
'parent' => 0,
'name' => 'Main B'
]
];
I want to convert it into:
$categoryTree = [
0 => [
'id' => 1360,
'parent' => 0,
'name' => 'main A'
],
1 => [
'id' => 1361,
'parent' => 1360,
'name' => 'sub a1'
],
2 => [
'id' => 57,
'parent' => 1360,
'name' => 'sub a2'
],
3 => [
'id' => 10,
'parent' => 0,
'name' => 'Main B'
]
];
It is rather simple. You walk recursively and only make a recursive call if the node has the key children. During the iteration in the foreach loop, keep collecting results in an result array.
<?php
function flatten($tree, &$results){
foreach($tree as $kid){
$kid_copy = $kid;
unset($kid_copy['children']);
$results[] = $kid_copy;
if(isset($kid['children'])) flatten($kid['children'], $results);
}
}
Online Demo
Alternatively, using a generator, which then doesn't need the second argument:
function recurIter($arr) {
foreach ($arr as $item) {
$orig = $item;
unset($item["children"]);
yield $item;
if (isset($orig["children"])) yield from recurIter($orig["children"]);
}
}
$result = iterator_to_array(recurIter($categoryTree), false);
Here is my array:
$list = array(
array('id' => 3, 'name' => 'Phones', 'parent_id' => 0,),
array('id' => 256, 'name' => 'Accessories', 'parent_id' => 0,),
array('id' => 308, 'name' => 'Appliances', 'parent_id' => 0,),
array('id' => 1057, 'name' => 'Smart', 'parent_id' => 0,),
array('id' => 1065, 'name' => 'Smart Phones', 'parent_id' => 3,),
array('id' => 1066, 'name' => 'Feature Phones', 'parent_id' => 3,),
array('id' => 1069, 'name' => 'Samsung', 'parent_id' => 1065,),
array('id' => 1070, 'name' => 'Apple', 'parent_id' => 1065,),
array('id' => 1072, 'name' => 'Apple', 'parent_id' => 1066,),
array('id' => 1075, 'name' => 'Tablets', 'parent_id' => 0,),
array('id' => 1076, 'name' => 'Samsung', 'parent_id' => 1066,),
array('id' => 1077, 'name' => 'All Brands', 'parent_id' => 1075,),
array('id' => 1078, 'name' => 'Samsung', 'parent_id' => 1077,),
array('id' => 1079, 'name' => 'Protector', 'parent_id' => 256,),
array('id' => 1080, 'name' => 'Power', 'parent_id' => 256,),
array('id' => 1081, 'name' => 'Cable', 'parent_id' => 256,),
array('id' => 1082, 'name' => 'Memory', 'parent_id' => 256,),
);
This is the code I categorized:
function quote_make_tree($list,$deep=1, $root = 0)
{
$tree = $packData = [];
foreach ($list as $row) {
$packData[$row['id']] = $row;
}
foreach ($packData as $key => $val) {
if ($val['parent_id'] == $root) {
$tree[] = &$packData[$key];
} else {
$packData[$val['parent_id']]['children'][] = &$packData[$key];
}
}
return $tree;
}
I want to add a deep parameter $deep to quote_make_tree to control the depth of classification.
The result I want:
If $deep = 1 Get only data with parent_id = 0:
$one = array(
0 => array('id' => 3, 'name' => 'Phones', 'parent_id' => 0,),
1 => array('id' => 256, 'name' => 'Accessories', 'parent_id' => 0,),
2 => array('id' => 308, 'name' => 'Appliances', 'parent_id' => 0,),
3 => array('id' => 1057, 'name' => 'Smart', 'parent_id' => 0,),
4 => array('id' => 1075, 'name' => 'Tablets', 'parent_id' => 0,),
);
If $deep = 2,Get level 2 classification below level 1 classification,if $deep=3,Get all 1,2,3 classifications
I have tried get all the data first, then delete the data according to $deep.here is demo,thanks folks
This might be easier to solve using a recursive method. This allows you to check the depth and if you want more details then it will call itself to add in more layers. Each time calling itself you just take one off the depth...
function quote_make_tree($list, $deep=1, $root = 0) {
$output = [];
foreach ( $list as $listItem ) {
if ( $listItem['parent_id'] == $root ) {
if ( $deep > 1 ) {
$listItem['children'] = quote_make_tree($list, $deep-1, $listItem['id']);
}
$output[] = $listItem;
}
}
return $output;
}
This question already has an answer here:
Creating parent-child array PHP
(1 answer)
Closed 4 years ago.
I want to group by key this array:
$arr = [
['id' => 1, 'name' => 'a'],
['id' => 2, 'parent' => 1, 'name' => 'a-child'],
['id' => 3, 'parent' => 1, 'name' => 'a-child-2'],
['id' => 4, 'name' => 'c'],
];
To be like this:
['id' => 1, 'name' => 'a', 'child' => [
['id' => 2, 'parent' => 1, 'name' => 'a-child'],
['id' => 3, 'parent' => 1, 'name' => 'a-child-2'],
]],
['id' => 4, 'name' => 'c'],
or group them by specific key, which element will be a parent.
I am using PHP.
You can use this for 1 level deep.
$arr = [
['id' => 1, 'name' => 'a'],
['id' => 2, 'parent' => 1, 'name' => 'a-child'],
['id' => 3, 'parent' => 1, 'name' => 'a-child-2'],
['id' => 4, 'name' => 'c'],
];
$new = [];
foreach($arr as $key => $row) {
if(!isset($row['parent'])) $new[$row['id']] = $row;
}
foreach($arr as $key => $child) {
if(isset($child['parent'])) {
$new[$child['parent']]['child'][] = $child;
}
}
print_r($new);
I have an array like this:
0 => ['id'=> 1, 'name' => 'A', 'parent_id' => null],
1 => ['id'=> 2, 'name' => 'A', 'parent_id' => 1],
2 => ['id'=> 3, 'name' => 'A', 'parent_id' => 2],
3 => ['id'=> 4, 'name' => 'A', 'parent_id' => 2],
4 => ['id'=> 5, 'name' => 'A', 'parent_id' => 4]
How can I iterate over this to create a nested array where items are inside of each other based on their parent_id?
Result to look like something like this:
0 => ['id'=> 1, 'name' => 'A', 'parent_id' => null, 'children' => [['id'=> 2, 'name' => 'A', 'parent_id' => 1, 'children' => [['id'=> 3, 'name' => 'A', 'parent_id' => 2], ['id'=> 4, 'name' => 'A', 'parent_id' => 2, 'children' => [['id'=> 4, 'name' => 'A', 'parent_id' => 4]]]]]]]
Use recursive function :
$arr = array(
0 => ['id'=> 1, 'name' => 'A', 'parent_id' => null],
1 => ['id'=> 2, 'name' => 'A', 'parent_id' => 1],
2 => ['id'=> 3, 'name' => 'A', 'parent_id' => 1],
3 => ['id'=> 4, 'name' => 'A', 'parent_id' => 2],
);
function add_childs(array $elements, $parentId = null) {
$parent = array();
foreach ($elements as $element) {
if ($element['parent_id'] == $parentId) {
echo "in if".$element['id']."<br>";
$children = add_childs($elements, $element['id']);
if ($children) {
$element['children'] = $children;
}
$parent[] = $element;
}
}
return $parent;
}
$result = add_childs($arr);
print_r($result);
example : https://eval.in/745350
EDIT : I understood the question other way (parent attached to child)...
You have to iterate over users to look for every parent/child pairing.
<?php
$users = [
0 => ['id'=> 1, 'name' => 'A', 'parent_id' => null],
1 => ['id'=> 2, 'name' => 'B', 'parent_id' => 1],
2 => ['id'=> 3, 'name' => 'C', 'parent_id' => 2],
3 => ['id'=> 4, 'name' => 'D', 'parent_id' => 2],
3 => ['id'=> 4, 'name' => 'E', 'parent_id' => 4]
];
foreach($users as $user){
foreach($users as &$parent){
if($user['parent_id'] == $parent['id']){
$parent['children'][] = $user;
}
}
}
var_dump($users);
?>
I'm stuck with transforming flat array to multidimensional tree like. I have already done it, but I used references, which creates another set of problems down the line, so I need to do this without references.
Input array:
Array
[
1 =>[
'content_id' => 1,
'sort_order' => 1,
'level' => 1
],
2 =>[
'content_id' => 7,
'sort_order' => 2,
'level' => 2
],
3 =>[
'content_id' => 4,
'sort_order' => 3,
'level' => 2
],
4 =>[
'content_id' => 2,
'sort_order' => 4,
'level' => 3
],
5 =>[
'content_id' => 3,
'sort_order' => 5,
'level' => 1
],
6 =>[
'content_id' => 6,
'sort_order' => 6,
'level' => 1
],
7 =>[
'content_id' => 5,
'sort_order' => 7,
'level' => 2
]
]
Output array:
1 => [
'id' = 1,
'visited' = 0,
'children' => [
2 => [
'id' => 7,
'visited' => 0,
'children' => []
],
3 => [
'id' => 4,
'visited' => 0,
'children' => [
4 => [
'id' = 2,
'visited' = 0,
'children' => []
]
]
],
5 => [
'id' => 3,
'visited' => 0,
'children' => []
],
6 => [
'id' => 6,
'visited' => 0,
'children' => [
7 => [
'id' => 5,
'visited' => 0,
'children => []
]
]
]
Any idea how to tackle a problem like this without having direct parent relation set? I can use recursion, but references are problem.
Oooh, this kind of problems do tickle my fancy. So, here is my solution:
<?php
$origArray = array(
array('content_id' => 1, 'sort_order' => 1, 'level' => 1),
array('content_id' => 7, 'sort_order' => 2, 'level' => 2),
array('content_id' => 4, 'sort_order' => 3, 'level' => 2),
array('content_id' => 2, 'sort_order' => 4, 'level' => 3),
array('content_id' => 3, 'sort_order' => 5, 'level' => 1),
array('content_id' => 6, 'sort_order' => 6, 'level' => 1),
array('content_id' => 5, 'sort_order' => 7, 'level' => 2),
);
function sortByOrder($a, $b) {
if ($a['sort_order'] == $b['sort_order']) {
return 0;
}
return ($a['sort_order'] < $b['sort_order']) ? -1 : 1;
}
function createHierarchicalArray($arr) {
$result = array();
foreach ($arr as $el) {
$result = insertArrayElement($result, $el['content_id'], $el['level']);
}
return $result;
}
function insertArrayElement($array, $id, $level, $currentLevel = 1) {
if ($level > $currentLevel) {
$ids = array_keys($array);
$currentId = end($ids);
if (!isset($array[$currentId]['children'])) {
$array[$currentId]['children'] = array();
}
$array[$currentId]['children'] = insertArrayElement($array[$currentId]['children'], $id, $level, $currentLevel + 1);
} else {
$array[$id] = array();
}
return $array;
}
// Could do without this, if the array is already sorted. Otherwise it's a necessary step.
uasort($origArray, 'sortByOrder');
$result = createHierarchicalArray($origArray);
var_dump($result);
Edit: Changed the code to incorporate the changes in the question.