PHP: Modifying array recursively? - php

I have tried to make a function that iterates through the following array to flatten it and add parent id to children, where applicable. I just can't make it work, so I hope that anyone here has an idea of what to do:
Here's the starting point:
Array
(
[0] => Array (
[id] => 1
[children] => array (
[id] => 2
[children] => Array (
[0] => Array (
[id] => 3
)
)
)
)
The expected result :
Array (
[0] => array (
[id] => 1
)
[1] => array (
[id] => 2
)
[2] => array (
[id] => 3,
[parent] => 2
)
)
Hope that anyone can point me in the right direction. Thanks a lot!
Solution (Thanks to Oli!):
$output = array();
function dejigg($in) {
global $output;
if (!isset($in['children'])) {
$in['children'] = array();
}
$kids = $in['children'] or array();
unset($in['children']);
if (!isset($in['parent'])) {
$in['parent'] = 0; // Not neccessary but makes the top node's parent 0.
}
$output[] = $in;
foreach ($kids as $child) {
$child['parent'] = $in['id'];
dejigg($child); // recurse
}
return $output;
}
foreach ($array as $parent) {
$output[] = dejigg($parent);
}
$array = $output;
print("<pre>".print_r($array,true)."</pre>");

I've tested it this time. This does work!
$input = array( array('id' => 1, 'children'=>array( array('id'=>2, 'children'=>array( array('id'=>3) ) ) ) ) );
$output = [];
function dejigg($in) {
global $output;
$kids = $in['children'] or array();
unset($in['children']);
$output[] = $in;
foreach ($kids as $child) {
$child['parent'] = $in['id'];
dejigg($child); // recurse
}
}
foreach ($input as $parent)
dejigg($parent);
print_r($output);
And it returns:
Array
(
[0] => Array
(
[id] => 1
)
[1] => Array
(
[id] => 2
[parent] => 1
)
[2] => Array
(
[id] => 3
[parent] => 2
)
)

Related

PHP : Replacing keys with incremental integer

I have this stdClass Object
Array (
[0] => stdClass Object ( [criteria1] => 1 [criteria2] => 2 [criteria3] => 2 )
[1] => stdClass Object ( [criteria1] => 2 [criteria2] => 1 [criteria3] => 1 )
[2] => stdClass Object ( [criteria1] => 1 [criteria2] => 1 [criteria3] => 1 )
)
I want to replace the keys into an integer like below
Array (
[0] => stdClass Object ( [0] => 1 [1] => 2 [2] => 2 )
[1] => stdClass Object ( [0] => 2 [1] => 1 [2] => 1 )
[2] => stdClass Object ( [0] => 1 [1] => 1 [2] => 1 )
)
Then I add this function, $arr is for the array of object, $len is for the number of columns of the array
function replace_key($arr,$len) {
$temp_array = array();
foreach ($arr as $key => $val) {
$object = new stdClass();
$x = (array) $val;
foreach ($x as $key2 => $value) {
for ($i=0; $i < $len; $i++) {
$new_key = $i;
$object->$new_key = $value;
}
}
$temp_array[] = $object;
}
return $temp_array;
}
But it resulted this output (the keys are already like how I want but the values are all wrong)
Array (
[0] => stdClass Object ( [0] => 2 [1] => 2 [2] => 2 )
[1] => stdClass Object ( [0] => 1 [1] => 1 [2] => 1 )
[2] => stdClass Object ( [0] => 1 [1] => 1 [2] => 1 )
)
I have no idea what part I did it wrong, I already tried to fix it for several hours but nothing seemed to workout and that function code is far the best I could do. Please help me, I'm so stucked.
Try this code
<?php
$a = (object)array("criteria1"=>1,"criteria2"=>2,"criteria3"=>2);
$b = (object)array("criteria1"=>2,"criteria2"=>1,"criteria3"=>1);
$c = (object)array("criteria1"=>1,"criteria2"=>1,"criteria3"=>1);
$test = array($a, $b,$c);
function replace_key($arr) {
foreach ($arr as $key => $val) {
$object =array();
$object =array_values((array)$val);
$temp_array[] = (object)$object;
}
return $temp_array;
}
print_r(replace_key($test));
?>
working code
function replace_key($arr, $len = null)
{
$results = [];
foreach ($arr as $ar) {
$array = array_values((array)$ar);
$results[] = (object)array_slice($array, 0, $len);
}
return $results;
}

Flatten multidimensional array PHP

I need to flatten a PHP array but having some issues getting the desired results.
Array
(
[0] => Array
(
[case_code_id] => 1
[parent_id] => 0
[case_code] => Main A
[sub_codes] => Array
(
[0] => Array
(
[case_code_id] => 3
[parent_id] => 1
[case_code] => Sub A
[sub_codes] => Array
(
[0] => Array
(
[case_code_id] => 5
[parent_id] => 3
[case_code] => Sub Sub A
[sub_codes] => Array
(
)
)
)
)
[1] => Array
(
[case_code_id] => 4
[parent_id] => 1
[case_code] => Sub B
[sub_codes] => Array
(
)
)
)
)
[1] => Array
(
[case_code_id] => 2
[parent_id] => 0
[case_code] => Main B
[sub_codes] => Array
(
)
)
)
But I would like to convert this to the following:
Array
(
[0] => Array
(
[case_code_id] => 1
[parent_id] => 0
[case_code] => Main A
)
[1] => Array
(
[case_code_id] => 3
[parent_id] => 1
[case_code] => Sub A
)
[2] => Array
(
[case_code_id] => 5
[parent_id] => 3
[case_code] => Sub Sub A
)
[3] => Array
(
[case_code_id] => 4
[parent_id] => 1
[case_code] => Sub B
)
[4] => Array
(
[case_code_id] => 2
[parent_id] => 0
[case_code] => Main B
[sub_codes] => Array
)
I have tried several loops but nothing returns the full array.
Here is what I have for my loop:
public function array_flatten($array,$list=array()){
for ($i=0;$i<count($array);$i++) {
$results[] = array(
'case_code_id'=>$array[$i]['case_code_id'],
'case_code'=>$array[$i]['case_code'],
'parent_id'=>$array[$i]['parent_id']
);
if (count($array[$i]['sub_codes']) > 0) {
$this->array_flatten($array[$i]['sub_codes'],$results);
} else {
$results[] = $array[$i];
}
}
return $results;
}
And I'm calling it like this: ($multi contains the multidimensional array)
$flat = $this->array_flatten($multi);
The variable $multi is created from this function:
public function build_case_code_tree(array $elements, $parentId = 0) {
$branch = array();
foreach ($elements as $element) {
if ($element['parent_id'] == $parentId) {
$children = $this->build_case_code_tree($elements, $element['case_code_id']);
$element['sub_codes'] = $children;
$branch[] = $element;
}
}
return $branch;
}
Any thoughts?
function array_flatten($a, $flat = []) {
$entry = [];
foreach ($a as $key => $el) {
if (is_array($el)) {
$flat = array_flatten($el, $flat);
} else {
$entry[$key] = $el;
}
}
if (!empty($entry)) {
$flat[] = $entry;
}
return $flat;
}
print_r(array_flatten($multi));
You're not using $list anywhere in the code, and nothing is passed by reference.
You're close, but your function should use $list in the place of $results, and it should receive $list by reference and modifying it in place instead of returning it.
Something like this (untested though):
function array_flatten($array,&$list=array()){
for ($i=0;$i<count($array);$i++) {
$list[] = array(
'case_code_id'=>$array[$i]['case_code_id'],
'case_code'=>$array[$i]['case_code'],
'parent_id'=>$array[$i]['parent_id']
);
if (count($array[$i]['sub_codes']) > 0) {
$this->array_flatten($array[$i]['sub_codes'],$list);
} else {
$list[] = $array[$i];
}
}
}
And calling it like this:
$flat = Array();
$this->array_flatten($multi, $flat);
// Result is inside $flat now

How to convert multidimensional recursive array into single dimensional array in PHP?

I have an array which comes out by calling a recursion function on the basis of parent id. This array is an n level multidimensional array.
What I want is to break this array into single dimensional, so that every child comes just after their parent.
I am using following function to first convert into recursive tree.
function formatTree($tree, $parent){
$tree2 = array();
foreach($tree as $i => $item){
if($item['cat_parent_id'] == $parent){
$tree2[$item['cat_id']] = $item;
$tree2[$item['cat_id']]['submenu'] = formatTree($tree, $item['cat_id']);
}
}
return $tree2;
}
This is the array I have.
Array
(
[58] => Array
(
[cat_id] => 58
[cat_name] => Desserts
[cat_parent_id] => 0
[submenu] => Array
(
[535] => Array
(
[cat_id] => 535
[cat_name] => dessert child
[cat_parent_id] => 58
[submenu] => Array
(
)
)
)
)
[56] => Array
(
[cat_id] => 56
[cat_name] => Biryani & Rice
[cat_parent_id] => 0
[submenu] => Array
(
)
)
)
This is how I want this.
Array
(
[0] => Array
(
[cat_id] => 58
[cat_name] => Desserts
[cat_parent_id] => 0
[submenu] => Array
(
)
)
[1] => Array
(
[cat_id] => 535
[cat_name] => dessert child
[cat_parent_id] => 58
[submenu] => Array
(
)
)
[2] => Array
(
[cat_id] => 56
[cat_name] => Biryani & Rice
[cat_parent_id] => 0
[submenu] => Array
(
)
)
)
It's almost 2020. I know it's a bit late but for those who are googling around: Their answers were close but they're only returning the parent elements. I've tweaked it a little bit to make it work (using array_merge).
function array_single_dimensional($items)
{
$singleDimensional = [];
foreach ($items as $item) {
$children = isset($item['children']) ? $item['children'] : null; //temporarily store children if set
unset($item['children']); //delete children before adding to new array
$singleDimensional[] = $item; // add parent to new array
if ( !empty($children) ){ // if has children
//convert children to single dimensional
$childrenSingleDimensional = array_single_dimensional($children);
//merge the two, this line did the trick!
$singleDimensional = array_merge($singleDimensional, $childrenSingleDimensional);
}
}
return $singleDimensional;
}
$singleDimensionalArray = array_single_dimensional($multidimensionalArray);
So, I assume you can change your initial function to make an array like the second one... then you should update your function like this:
function formatTree($tree, $parent){
$tree2 = array();
foreach($tree as $i => $item){
if($item['cat_parent_id'] == $parent){
$item['submenu'] = array();
$tree2[] = $item;
formatTree($tree, $item['cat_id']);
}
}
return $tree2;
}
This should work. For your use case you don't need a parent_id in your function.
function formatTree($tree){
$tree2 = array();
foreach($tree as $i => $item){
$submenu = $item['submenu'];
unset($item['submenu']); //clear submenu of parent item
$tree2[] = $item;
if(!empty($submenu)){
$sub = formatTree($submenu); //submenu's return as array in array
$tree2[] = $sub[0]; // remove outer array
}
}
return $tree2;
}
Just try this,
$array = Array
(
"58" => Array
(
"cat_id" => 58,
"cat_name" => "Desserts",
"cat_parent_id" => 0,
"submenu" => Array
(
"535" => Array
(
"cat_id" => 535,
"cat_name" => "dessert child",
"cat_parent_id" => 58,
"submenu" => Array
()
)
)
),
"56" => Array
(
"cat_id" => 56,
"cat_name" => "Biryani & Rice",
"cat_parent_id" => 0,
"submenu" => Array
()
)
);
function singledimensional($array)
{
$res = array();
foreach ($array as $i => $item) {
$temparr = $item;
$item['submenu'] = array();
$res[] = $item;
if (!empty($temparr['submenu']) ){
$child = singledimensional($temparr['submenu']);
$res[] = $child[0];
}
}
return $res;
}
echo '<pre>';
print_r(singledimensional($array));
echo '</pre>';
Output:
Array
(
[0] => Array
(
[cat_id] => 58
[cat_name] => Desserts
[cat_parent_id] => 0
[submenu] => Array
(
)
)
[1] => Array
(
[cat_id] => 535
[cat_name] => dessert child
[cat_parent_id] => 58
[submenu] => Array
(
)
)
[2] => Array
(
[cat_id] => 56
[cat_name] => Biryani & Rice
[cat_parent_id] => 0
[submenu] => Array
(
)
)
)
I hope this will help you :)
(PHP 4 >= 4.0.1, PHP 5)
array_merge_recursive — Merge two or more arrays recursively
`function array_merge_recursive_distinct ( array &$array1, array &$array2 )
{
$merged = $array1;
foreach ( $array2 as $key => &$value )
{
if ( is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) )
{
$merged [$key] = array_merge_recursive_distinct ( $merged [$key], $value );
}
else
{
$merged [$key] = $value;
}
}
return $merged;
}
?>`

php | Bug with recursion

I have a problem with my recursional function. May be you can help me.
My function below:
function showTree($items, $level = 0) {
$arr = [];
foreach ($items as $item) {
$arr[] = str_repeat(":", $level * 2) . $item['name'] . "<br />";
if (!empty($item['children'][0])) {
$level++;
$arr[] = $this->showTree($item['children'], $level);
}
}
return $arr;
}
And this generate the output:
Array
(
[0] => Category1
[1] => Array
(
[0] => ::SubCategory2
[1] => ::SubCategory1
[2] => Array
(
[0] => ::::SubSubCategory
)
)
)
But I need a little bit other data as my output:
Array
(
[0] => Category1
[1] => ::SubCategory2
[2] => ::SubCategory1
[3] => ::::SubSubCategory
)
Where is my mistake? Thanks!
P>S:
Input:
Array
(
[0] => Array
(
[id] => 1
[name] => Category1
[parent] => 0
[children] => Array
(
[0] => Array
(
[id] => 4
[name] => SubCategory2
[parent] => 1
[children] => Array
(
)
)
[1] => Array
(
[id] => 2
[name] => SubCategory1
[parent] => 1
[children] => Array
(
[0] => Array
(
[id] => 3
[name] => SubSubCategory
[parent] => 2
[children] => Array
(
)
)
)
)
)
)
)
Change this line:
$arr[] = $this->showTree($item['children'], $level);
to:
$arr = array_merge($arr, $this->showTree($item['children'], $level));
I.e. don't add the array returned while walking the children as a new value into the current array but append the values from it to the current array.
Try this:
function showTree($items, $level = 0, &$arr = array()) {
foreach ($items as $item) {
$arr[] = str_repeat(":", $level * 2) . $item['name'] . "<br />";
if (!empty($item['children'][0])) {
$level++;
$this->showTree($item['children'], $level, $arr);
}
}
return $arr;
}

Arrange PHP Multidimensional Array By Inner Index

How to arrange this array by last inner index ( 0, 1, 2 ) and get the value of the last inner index as the value of each second index:
Array
(
[text] => Array
(
[grid] => Array
(
[0] => 3
[1] => 4
[2] => 5
)
[image] => Array
(
[0] =>
[1] =>
[2] =>
)
[align] => Array
(
[0] => left
[1] => right
[2] => left
)
[title] => Array
(
[0] =>
[1] =>
[2] =>
)
[content] => Array
(
[0] =>
[1] =>
[2] =>
)
)
)
And have the results as below:
Array
(
[text] => Array
(
[0] => Array
(
[grid] => 3
[image] =>
[align] => left
[title] =>
[content] =>
)
[1] => Array
(
[grid] => 4
[image] =>
[align] => right
[title] =>
[content] =>
)
[2] => Array
(
[grid] => 5
[image] =>
[align] => left
[title] =>
[content] =>
)
)
)
This will do the work
function restructure($arr){
$newArr = array();
foreach($arr as $k => $v){
foreach($v as $k1 => $v1){
foreach($v1 as $k2 => $v2){
$newArr[$k][$k2][$k1] = $v2;
}
}
}
return $newArr;
}
As SiGanteng suggested, i dont see other ways than a for/foreach loop:
function buildArray($source, $key = false)
{
// Build the new array
$new_array = array();
// Define groups
$groups = $key === false ? array_keys($source) : array($key);
foreach($groups AS $group)
{
// Get the keys
$keys = array_keys($array[$group]);
// Count the values
$num_entries = count($array[$group][$keys[0]]);
for($i = 0; $i < $num_entries; $i++)
{
foreach($keys AS $key)
{
$new_array[$group][$i][$key] = $array[$group][$key][$i];
}
}
}
return $new_array;
}
This allow you to define the key you need to build; If not specified, the function build the array for every key.
This should work.
function formatit($arr) {
$new = array();
foreach($arr as $k=>$v) {
foreach($v as $k1=>$v1) {
$new[$k1][$k] = $v1;
}
}
return $new;
}
Tested. Call it as
$arr['text'] = formatit($arr['text']);
http://ideone.com/rPzuR

Categories