Nesting Array Items Based on a Value - php

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);
?>

Related

How to merge arrays based on value in php?

I am having 2 arrays and i have to merge that arrays with similar values. i tried for each and basic functions of php for array merging but not getting proper result.
i tried below thing but it wont work for me as i am having multiple data in second array. as you can see in child array i am having multiple records and i want to keep that together inside base array.
$base= [
['id' => 1],
['id' => 2],
['id' => 3],
['id' => 4],
];
$child = [
['id' => 1, 'size' => 'SM'],
['id' => 1, 'size' => 'LK'],
['id' => 2, 'size' => 'XL'],
['id' => 4, 'size' => 'LG'],
['id' => 3, 'size' => 'MD'],
];
foreach(array_merge($base, $child) as $el){
$merged[$el['id']] = ($merged[$el['id']] ?? []) + $el;
}
Output :
array (
1 =>
array (
'id' => 1,
'size' => 'SM',
),
2 =>
array (
'id' => 2,
'size' => 'XL',
),
3 =>
array (
'id' => 3,
'size' => 'MD',
),
4 =>
array (
'id' => 4,
'size' => 'LG',
),
)
desired output :
array (
1 =>
array (
'id' => 1,
1 => array('size' => 'SM'),
2 => array('size' => 'LK'),
),
2 =>
array (
'id' => 2,
1 => array('size' => 'XL'),
),
3 =>
array (
'id' => 3,
1 => array('size' => 'MD'),
),
4 =>
array (
'id' => 4,
1 => array('size' => 'LG'),
),
)
Because your array $child have same key id value, and every you save the array, it always destroyed old array with same key id.
Here the working code :
<?php
$base= [
['id' => 1],
['id' => 2],
['id' => 3],
['id' => 4],
];
$child = [
['id' => 1, 'size' => 'SM'],
['id' => 1, 'size' => 'LK'],
['id' => 2, 'size' => 'XL'],
['id' => 4, 'size' => 'LG'],
['id' => 3, 'size' => 'MD'],
];
foreach(array_merge($base, $child) as $el){
if(!isset($el['size'])){ // $base doesn't have 'size' key
$merged[$el['id']] = []; // fill with empty array
}else{
$merged[$el['id']][] = $el;
}
// bellow code is for start array index from 1 instead of 0
array_unshift($merged[$el['id']],"");
unset($merged[$el['id']][0]);
}
print_r($merged);

Group array by specific key - PHP [duplicate]

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);

Get simple recursive from table with id_parent

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]);

php/laravel - How to arrange arrays according to the highest number and number them

I have a table with marks of students in it. i have 2 record
student a = 90;
student b = 85;
I want to get the all the results for the total score of the students and then give the students positions in the class e.g
student a = 90; //first position
student b = 85; //second position
i have a column called position which is null after saving the total score of the students how can i check who is higher/lower and give them positions
Considering you are using Laravel and you know how to use collections. This answer inspired from Adam Wathan's book.
$scores = collect([
['score' => 80, 'name' => 'a'],
['score' => 85, 'name' => 'b'],
['score' => 80, 'name' => 'k'],
['score' => 75, 'name' => 'h'],
['score' => 90, 'name' => 'w'],
['score' => 90, 'name' => 'v'],
['score' => 50, 'name' => 'r'],
['score' => 45, 'name' => 't'],
]);
function rankandscore($scores){
return collect($scores)
->sortByDesc('score')
->zip(range(1, $scores->count()))
->map(function ($scoreAndRank){
list($score, $rank) = $scoreAndRank;
return array_merge($score, [
'rank' => $rank
]);
})
->groupBy('score')
->map(function ($tiedScores){
$lowestRank = $tiedScores->pluck('rank')->min();
return $tiedScores->map(function ($rankedScore) use ($lowestRank){
return array_merge($rankedScore, [
'rank' => $lowestRank,
]);
});
})
->collapse()
->sortBy('rank');
}
$score = rankandscore($scores);
dd($score);
// will give output like this.
[
['score' => 90, 'name' => 'w', 'rank' => 1],
['score' => 90, 'name' => 'v', 'rank' => 1],
['score' => 85, 'name' => 'b', 'rank' => 3],
['score' => 80, 'name' => 'a', 'rank' => 4],
['score' => 80, 'name' => 'k', 'rank' => 4],
['score' => 75, 'name' => 'h', 'rank' => 6],
['score' => 50, 'name' => 'r', 'rank' => 7],
['score' => 45, 'name' => 't', 'rank' => 8],
]
You can use this function to modify according to your needs
More Info https://laravel.com/docs/5.5/eloquent-collections

PHP returning all IDs from an array of parent/children given an id

Having a problem here that maybe someone can help me with. Hours of searching couldn't find the solution so I'm at my wit's end.
I have an array,
$array = array(
array('id' => 1, 'parent_id' => 0, 'name' => 'Main'),
array('id' => 2, 'parent_id' => 0, 'name' => 'Something'),
array('id' => 3, 'parent_id' => 1, 'name' => 'Child of Main'),
array('id' => 4, 'parent_id' => 3, 'name' => 'Child of Child of Main'),
...
);
I want a function that will give me all of the ids of the parents for a given node, i.e.
$ids = getIDs(4);
would return an array of {3, 1}
Any suggestions? Thank you in advance.
I've made something similar to RiaD (but on my own). It works well with the structure you already have.
<?php
$array = array(
array('id' => 1, 'parent_id' => 0, 'name' => 'Main'),
array('id' => 2, 'parent_id' => 0, 'name' => 'Something'),
array('id' => 3, 'parent_id' => 1, 'name' => 'Child of Main'),
array('id' => 4, 'parent_id' => 3, 'name' => 'Child of Child of Main'),
);
$parents = array();
function getIDs($id){
global $array, $parents;
$tmp = $array[$id-1]['parent_id'];
if($tmp){
array_push($parents, $tmp);
getIDs($tmp);
}
}
getIDs(4);
var_dump($parents);
?>
Is it possible to make structure like this?
$array = array(
1=>array('id' => 1, 'parent_id' => 0, 'name' => 'Main'),
2=>array('id' => 2, 'parent_id' => 0, 'name' => 'Something'),
3=>array('id' => 3, 'parent_id' => 1, 'name' => 'Child of Main'),
4=>array('id' => 4, 'parent_id' => 3, 'name' => 'Child of Child of Main'),
...
);
with or without 'id' inside array
This one should works with this structure
function getIds($array,$x){
if(!$array[$x]['parent_id'])
return array();
else
return array_merge(array($array[$x]['parent_id']),getIds($array,$array[$x]['parent_id']));
}
you can try foreach loop or use array_count_values

Categories