Group array by specific key - PHP [duplicate] - php

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

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

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

Nesting Array Items Based on a Value

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

How to generate a tree-like array from flat array without use of references

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.

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