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'
            ]
        ],
    ];
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;
}
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 );

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

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

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

1 Comment

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

Your Answer

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.