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
  • 43,625
  • 12
  • 83
  • 136
Alex Kneller
  • 413
  • 4
  • 15

5 Answers5

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;
}
Anly
  • 312
  • 3
  • 11
  • Building out a multi-dimensional array as if it were a tree? This answer deserves more upvotes –  Nov 22 '15 at 15:04
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 );

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);
?>
Itay Elkouby
  • 344
  • 1
  • 15
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;
    }
 } 
Ben
  • 673
  • 3
  • 11
  • thanks ,but as i comment for another answer it have unlimited levels. – Alex Kneller Nov 22 '15 at 12:23
  • 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 ;) – Ben Nov 22 '15 at 12:25
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