Flatten Array php - php

I'm trying to flat a multidimensional array to a given specific format.
I have a tree that is saved as a nested array, which is ok, but the function given to render the array in the UI expects only one array and, per each child, an independent array. Instead of the nested array, each option should be at the same level.
This is how my var_dump of my array:
(
[id] => 1
[name] => some data.
[emoji] => 🐕
[parent_id] =>
[children] => Array
(
[0] => Array
(
[id] => 2
[name] => Food
[emoji] => 🥩
[parent_id] => 1
[children] => Array
(
)
)
[1] => Array
(
[id] => 3
[name] => some other data
[emoji] => 😌
[parent_id] => 1
[children] => Array
(
[0] => Array
(
[id] => 4
[name] => Massages
[emoji] => 💆
[parent_id] => 3
[children] => Array
(
)
)
[1] => Array
(
[id] => 5
[name] => Games
[emoji] => 🎾
[parent_id] => 3
[children] => Array
(
)
)
)
)
)
)
)
And the expected result should be:
0] => Array
(
[id] => 1
[name] => Rusty Corp.
[emoji] => 🐕
[parent_id] =>
)
[1] => Array
(
[id] => 2
[name] => Food
[emoji] => 🥩
[parent_id] => 1
)
[2] => Array
(
[id] => 3
[name] => Canine Therapy
[emoji] => 😌
[parent_id] => 1
)
[3] => Array
(
[id] => 4
[name] => Massages
[emoji] => 💆
[parent_id] => 3
)
[4] => Array
(
[id] => 5
[name] => Games
[emoji] => 🎾
[parent_id] => 3
)
I tried different approaches like array_merge or custom flattening function but can't nail with the expected results, any suggestions?
Edit:
This is my flatten function:
private function flatten_array( array $array ) {
$return = array();
array_walk_recursive(
$array,
function( $a ) use ( &$return ) {
$return[] = $a;
}
);
return $return;
}

Here is a recursive function that will flatten the array, it will not take into account the null value of parent_id on the root element. Also the flattened array will start with the most nested elements at the start of the array and root element at the end.
function flatten_array($array, $flattened = []) {
$current = [];
foreach ($array as $key => $value) {
if (is_array($value))
$flattened = array_merge($flattened, flatten_array($value));
else
$current[$key] = $value;
}
$flattened[] = $current;
return array_filter($flattened);
}

Related

Issue in merge array and delete duplicate all array

I've merged two arrays. A duplicate entry is a deleted. Let me explain the as an example (I have compare array using user_id)
$array1 = Array
(
[0] => Array
(
[id] => 44
[user_id] => 2
[name] => jina_testl
[profilePhoto] =>
)
)
$array2 = Array
(
[0] => Array
(
[id] => 2
[user_id] => 3
[name] => demo_test1
[profilePhoto] =>
)
[1] => Array
(
[id] => 3
[user_id] => 2
[name] => abc
[profilePhoto] =>
)
[2] => Array
(
[id] => 4
[user_id] => 4
[name] => test
[profilePhoto] =>
)
)
I have merged array1 and array2 and duplicate array remove. I get the following output:
Array
(
[0] => Array
(
[id] => 44
[user_id] => 2
[name] => jina_testl
[profilePhoto] =>
)
[1] => Array
(
[id] => 2
[user_id] => 3
[name] => demo_test1
[profilePhoto] =>
)
[3] => Array
(
[id] => 4
[user_id] => 4
[name] => abc
[profilePhoto] =>
))
But I want such an output like this:
Array
(
[0] => Array
(
[id] => 2
[user_id] => 3
[name] => demo_test1
[profilePhoto] =>
)
[1] => Array
(
[id] => 4
[user_id] => 4
[name] => abc
[profilePhoto] =>
))
You could do something like the following: first get all the user_ids that we do not want to be included, by taking the intersection of the two columns.
If we then merge the two separate arrays and exclude the ones that are present in the array of unwanted IDs we should get our final result.
$userId = 'user_id';
$userIdsArray1 = array_column($array1, $userId);
$userIdsArray2 = array_column($array2, $userId);
// If we then take the negation we should get something similar to an exclusive or.
// Thus those in one or the other but not in both arrays.
$unwantedUserIds = array_intersect($userIdsArray1, $userIdsArray2);
$result = [];
foreach (array_merge($array1, $array2) as $record) {
if (!in_array($record[$userId], $unwantedUserIds)) {
$result[] = $record;
}
}
echo '<pre>', print_r($result, true), '</pre>';
Result:
Array
(
[0] => Array
(
[id] => 2
[user_id] => 3
[name] => demo_test1
[profilePhoto] =>
)
[1] => Array
(
[id] => 4
[user_id] => 4
[name] => test
[profilePhoto] =>
)
)

Update multidimensional array value depending on other sibling value

I have array this can be up to n element.
(
[children] => Array
(
[0] => Array
(
[id] => nhbs0123620cf897
[title] => Introduction
[children] => Array
(
[0] => Array
(
[id] => bylff0a76617c8
[title] => Courent3
[children] => Array
(
)
)
[1] => Array
(
[id] => xavs26efa2f51eb
[title] => Chapter
[children] => Array
(
)
)
[2] => Array
(
[id] => iezkd241d9d90
[title] => external
[children] => Array
(
)
)
[3] => Array
(
[id] => gmzh439c4f50
[title] => audio
[children] => Array
(
)
)
[4] => Array
(
[id] => niugd4e18b0
[title] => url
[children] => Array
(
)
)
[5] => Array
(
[id] => unpgdb1b7694
[title] => new
[children] => Array
(
)
)
[6] => Array
(
[id] => ssvc2025c0c8a
[title] => simple
[children] => Array
(
[0] => Array
(
[id] => ssvc2025c0c
[title] => later
[children] => Array
(
)
)
)
)
)
)
[1] => Array
(
[id] => rwtae5d9482
[title] => Summary
[children] => Array
(
[0] => Array
(
[id] => ssvc2025c0
[title] => later
[children] => Array
(
)
)
)
)
[2] => Array
(
[id] => rwtae5d9482709
[title] => Course
[children] => Array
(
)
)
)
)
Here I want to update title value depending on id for each element in array.
What i have tried
1 used array_walk_recursive here i can update data but while updating not able to check id value .
array_walk_recursive(array, function(&$value, $key) {
// not able to check if id == 'something' .this is what i need
if ($key == 'title') {
$value = 'updated data';
}
});
Second tried in for each loop but not able to hold array index to get actual array
function myfun($array,&$out){
foreach($array['children'] as $key=>$val){
if(!empty($val['children'])){
$out['children'][$key]['title'] = $val['title']; // this is not right key
$this->myfun($val,$out['children']);
}else{
$out['children'][$key]['title'] = $val['title']; // this is not right key
}
}
}
here also not able to return array in $out array.
Only thing i have that children key using this if any function can be written.
I am hoping this should be possible in php array functions.
You are close - all you need is to use the & - this will send the array as reference so any change on him will be on the original array. Can look in PHP manual for more knowledge.
Consider the following:
$arr = [["id" => 1, "title" => "aaa", "children" => []], ["id" => 2, "title" => "bbb", "children" => [["id" => 3, "title" => "ccc", "children" => []]]]];
function modifyTitle(&$arr, $id, $newVal) {
foreach($arr as &$e) {
if ($e["id"] == $id)
$e["title"] = $newVal;
modifyTitle($e["children"], $id, $newVal);
}
}
modifyTitle($arr, 3, "zzz");
print_r($arr); // now the original array children changed
Live example: https://3v4l.org/ZbiB9

sort an array with another array which has sorted keys

How to sort an 1st array with 2nd array which has sorted keys in 2nd array without using any loop.
1st Array.
$chunk = array(
[0] => Array
(
[id] => 212
[order] => 1
[title] => fdfdfdfdf
)
[1] => Array
(
[id] => 5
[order] => 2
[title] =>
)
[2] => Array
(
[id] => 781
[order] => 3
[title] =>
)
)
2nd array with sorted keys of 1st array.
$sort = array
(
[2] => 2
[0] => 0
[1] => 1
)
You could use array_map for that:
$arr = array_map(function($val) use($chunk){
return $chunk[$val];
}, $sort);
This is the output:
Array
(
[2] => Array
(
[id] => 781
[order] => 3
[title] =>
)
[0] => Array
(
[id] => 212
[order] => 1
[title] => fdfdfdfdf
)
[1] => Array
(
[id] => 5
[order] => 2
[title] =>
)
)
Now, if you want the keys to be 0,1,2..., you can use array_values, after mapping:
$arr = array_values($arr);
And the output:
Array
(
[0] => Array
(
[id] => 781
[order] => 3
[title] =>
)
[1] => Array
(
[id] => 212
[order] => 1
[title] => fdfdfdfdf
)
[2] => Array
(
[id] => 5
[order] => 2
[title] =>
)
)
Of course, there is no function for this. You'll have to do something similar
<?php
$chunk = [
// data
];
$sorted = [];
$sort = [
// ordered keys
];
foreach($sort as $keyToFind) {
foreach($chunk as $arrayElement) {
if($arrayElement['id'] == $keyToFind)) {
$sorted[$keyToFind] = $arrayElement;
}
}
}
As you can see, this is a bit time and ressources consumming because of the two imbricated foreaches. Let's hope your arrays are not so big

Shift Recursive nested child array to parent array PHP

I have an issue with forming a recursive array. That is shifting the child array nodes to direct elements to a parent array.
like from,
Array
(
[0] => Array
(
[id] => 1
[category_name] => flare
[parent_category_id] => 0
[childrenrecursive] => Array
(
[0] => Array
(
[id] => 2
[category_name] => analytics
[parent_category_id] => 1
[braincount] => Array
(
[count] => 3
[category_id] => 2
)
[childrenrecursive] => Array
(
[0] => Array
(
[id] => 4
[category_name] => sports analytics
[parent_category_id] => 2
[braincount] => Array
(
[count] => 4
[category_id] => 4
)
[childrenrecursive] => Array
(
)
)
)
)
[1] => Array
(
[id] => 3
[category_name] => cluster
[parent_category_id] => 1
[braincount] => Array
(
[count] => 4
[category_id] => 3
)
[childrenrecursive] => Array
(
)
)
)
)
)
to,
Array
(
[0] => Array
(
[id] => 1
[category_name] => flare
[parent_category_id] => 0
[childrenrecursive] => Array
(
[0] => Array
(
[id] => 2
[category_name] => analytics
[parent_category_id] => 1
[count] => 3
[category_id] => 2
[childrenrecursive] => Array
(
[0] => Array
(
[id] => 4
[category_name] => sports analytics
[parent_category_id] => 2
[count] => 4
[category_id] => 4
[childrenrecursive] => Array
(
)
)
)
)
[1] => Array
(
[id] => 3
[category_name] => cluster
[parent_category_id] => 1
[count] => 4
[category_id] => 3
[childrenrecursive] => Array
(
)
)
)
)
)
only by moving following child array append to parent in a recursive way.
[braincount] => Array
(
[count] => 4
[category_id] => 3
)
can anybody help me to format the array like specified.
Let's say $input is the array posted in the question:
/**
* If $value is an array then move the content of 'braincount' one level up
* (in $value) then call recursively for all its children.
*/
function moveUp($value)
{
// Not an array? Nothing to do; return the input value unchanged
if (! is_array($value)) {
return $value;
}
// Move the content of 'braincount' (if present) one level up
if (array_key_exists('braincount', $value)) {
$value = array_merge($value, $value['braincount']);
unset($value['braincount']);
}
// Apply the same operation to all children
return array_map(__FUNCTION__, $value);
}
// Verify it works
print_r(moveUp($input));

Children nodes moved to the root level on an hierarchy array

I have the following array on a hierarchy structure - It's basically an array with categories and its children under the 'child' key:
Array
(
[category_id] => 1
[parent_id] => 0
[name] => Commercial
[child] => Array
(
[0] => Array
(
[category_id] => 48
[parent_id] => 1
[name] => lights
[child] => Array
(
)
)
[1] => Array
(
[category_id] => 12
[parent_id] => 1
[name] => beacons
[child] => Array
(
[0] => Array
(
[category_id] => 91
[parent_id] => 12
[name] => blue beacons
[child] => Array
(
)
)
)
)
)
)
What I am trying to do is write a recursive function to reorganize this array as an ONE LEVEL array only. Instead of having its children inside the 'child' key, I want it to be part of the array root level. Like this:
[0] => Array
(
[category_id] => 1
[parent_id] => 0
[name] => Commercial
)
[1] => Array
(
[category_id] => 48
[parent_id] => 1
[name] => lights
)
[2] => Array
(
[category_id] => 12
[parent_id] => 1
[name] => beacons
)
[3] => Array
(
[category_id] => 91
[parent_id] => 12
[name] => blue beacons
)
Any ideas?
Thanks!
The following recursive function should serve your purpose:
function one_level_array($arr){
$ret = array();
$ret[] = array_diff_key($arr, array("child" => ""));
if(array_key_exists("child", $arr)){
foreach($arr["child"] as $child){
$ret = array_merge($ret, one_level_array($child));
}
}
return $ret;
}
DEMO

Categories