2

I am trying to created nested array from flat based on its keys. Also format of keys in original array can be changed if it will simplify task.

From :

$arr = [
 'player.name' => 'Joe',
 'player.lastName' => 'Snow',
 'team.name' => 'Stars',
 'team.picture.name' => 'Joe Snow Profile',
 'team.picture.file' => 'xxx.jpg'
 ];

To:

$arr = [
 'player' => [
 'name' => 'Joe'
 , 'lastName' => 'Snow'
 ]
 ,'team' => [
 'name'=> 'Stars'
 ,'picture' => [
 'name' => 'Joe Snow Profile'
 , 'file' =>'xxx.jpg'
 ]
 ],
 ];
mickmackusa
49.3k13 gold badges98 silver badges165 bronze badges
asked Nov 22, 2015 at 11:47
5
  • you need to convert in existing array or you have to create new array. Commented Nov 22, 2015 at 11:53
  • from array you have already exist ? Commented Nov 22, 2015 at 11:55
  • player.name is a single key ? Commented Nov 22, 2015 at 11:59
  • if you dont have . after it it single key else its group to be nested Commented Nov 22, 2015 at 12:03
  • My edited answer should fit but is very static. If you need a deeper recursion there would be another way. Commented Nov 22, 2015 at 12:23

5 Answers 5

6

Here is my take on it.
It should be able to handle arbitrary depth

function unflatten($arr) {
 $result = array();
 foreach($arr as $key => $value) {
 $keys = explode(".", $key); //potentially other separator
 $lastKey = array_pop($keys);
 $node = &$result;
 foreach($keys as $k) {
 if (!array_key_exists($k, $node))
 $node[$k] = array();
 $node = &$node[$k];
 }
 $node[$lastKey] = $value;
 }
 return $result;
}
answered Nov 22, 2015 at 13:06
Sign up to request clarification or add additional context in comments.

1 Comment

Building out a multi-dimensional array as if it were a tree? This answer deserves more upvotes
1

Combination of iteration and recursion. Could be simplified to just iterative.

$array = [
 'player.name' => 'Joe',
 'player.lastName' => 'Snow',
 'team.name' => 'Stars',
 'team.picture.name' => 'Joe Snow Profile',
 'team.picture.file' => 'xxx.jpg'
];
$newArray = array ();
foreach($array as $key=> $value) {
 $temp = array ();
 $keys = array_reverse (explode('.', $key));
 $temp[$keys[0]] = $value;
 for ($i = 1; $i < count($keys); $i++) {
 $temp[$keys[$i]] = $temp;
 unset ($temp [$keys [$i -1]]);
 }
 $newArray = array_merge_recursive($newArray,$temp);
}
var_dump($newArray );
answered Nov 22, 2015 at 14:23

2 Comments

Thanks, very elegant solution.
You are right your answer was more readable,but Anly's have better performance.
1

I received this question as a test, this is my answer:

<?php
function buildArray(&$newArray, $keys, $value)
{
 if (sizeof($keys) == 0) {
 return $value;
 } else {
 $key = array_shift($keys);
 if (isset($newArray[$key])) {
 $value = buildArray($newArray[$key], $keys, $value);
 if (is_array($value)) {
 $newArray[$key] += $value;
 } else {
 $newArray[$key] = $value;
 }
 $arr = $newArray;
 } else {
 $arr[$key] = buildArray($newArray, $keys, $value);
 }
 }
 return $arr;
}
$arr = [
 'player.name' => 'Joe',
 'player.lastName' => 'Snow',
 'team.name' => 'Stars',
 'team.picture.name' => 'Joe Snow Profile',
 'team.picture.file' => 'xxx.jpg',
];
$newArray = [];
foreach ($arr as $key => $value) {
 $explodedKey = explode(".", $key);
 $temp = buildArray($newArray, $explodedKey, $value);
 $newArray = array_merge($temp, $newArray);
}
print_r($newArray);
?>
answered Mar 8, 2016 at 8:31

Comments

0

You could do it like this

$newArr = []; 
for ($arr as $key => $val) {
 $tmp = explode ('.', $key);
 if (!array_key_exists ($tmp [0], $newArray){
 $newArray [$tmp [0]] = [];
 }
 $newArray [$tmp [0]][$tmp [1]] = $val;
 } 

edit: Damn didn't saw the third level in team.
Not very generic but should work for third level ;)

$newArr = []; 
for ($arr as $key => $val) {
 $tmp = explode ('.', $key);
 if (!array_key_exists ($tmp [0], $newArray){
 $newArray [$tmp [0]] = [];
 }
 if (count($tmp) > 2){
 if (!array_key_exists ($tmp [1], $newArray[$tmp [0]]){
 $newArray [$tmp [0]][$tmp[1]] = [];
 }
 $newArray [$tmp [0]][$tmp [1]][$tmp [2]] = $val;
 } else {
 $newArray [$tmp [0]][$tmp [1]] = $val;
 }
 } 
answered Nov 22, 2015 at 12:09

2 Comments

thanks ,but as i comment for another answer it have unlimited levels.
Ok. You could try it with a recursive function and split up first part of the string in every recursion. I have to leave now in 5 hours i could write you an example ;)
0

I think you can use something like this, for converting 2d array to nested tree. But You'll have to play with parent_id

https://github.com/denis-cto/flat-array-to-nested-tree

answered Aug 12, 2020 at 6:08

1 Comment

Please don't post just plain URLs without explanation and posting some code.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.