10

I have an array:

$array = [
    "main;header;up" => "main_header_up value",
    "main;header;bottom" => "main_header_bottom value",
    "main;bottom" => "main_bottom value",
    "main;footer;right;top" => "main_footer_right_top value"
];

What I'd like to get is explode the array keys into multidimensional array but keep the values and the result should be equivalent of this array:

$array = [
    "main" => [
        "header" => [
            "up" => "main_header_up value", 
            "bottom" => "main_header_bottom value"
        ],
        "bottom" => ["main_bottom value"],
        "footer" => [
            "right" => [
                "top" => "main_footer_right_top value
            ]
        ]
    ]
];

I guess I should state that the number of ; is not predetermined. There could be none or there could be 10 (or more) of them in a key / index.

Is there any elegant way to achieve this?

AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
Revenant
  • 2,942
  • 7
  • 30
  • 52
  • I think `explode` has nothing to do here. You could write your own function to parse such input. I recommend using nested objects (i.e. `main->header->up` and `main->bottom`..) etc – FindOut_Quran May 20 '16 at 21:58
  • Yeah, I'd also go for objects. I thought dealing with arrays in such manner would be a lot easier once done `json_decode / json_encode` would do the trick though. – Revenant May 20 '16 at 22:01
  • `explode` is part of the solution, but not the tricky one. Tricky is, that you'll have to write your own function to transfer those resulting arrays into a multidimentional array/object while keeping the values in the right place. – Jeff May 20 '16 at 22:04
  • @Jeff exactly, I can organize the new array exactly the way I want into new array but with an empty array as a value. I thought there might be an elegant way to deal with such case which I am not aware. – Revenant May 20 '16 at 22:06

2 Answers2

13

Here is what I use for things like this:

$result = array();

foreach($array as $path => $value) {
    $temp =& $result;

    foreach(explode(';', $path) as $key) {
        $temp =& $temp[$key];
    }
    $temp = $value;
}
    
print_r($result);
  • Loop the array and explode() the keys on ;
  • Loop the exploded values and create nested keys from those values
  • Assign the value of the original array element to the last key

My answer to How to write getter/setter to access multi-level array by key names? may help if you need some functions to do this.

AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
8

Here's solution

<?php
$array = [
    "main;header;up" => "main_header_up value",
    "main;header;bottom" => "main_header_bottom value",
    "main;bottom" => "main_bottom value",
    "main;footer;right;top" => "main_footer_right_top value"
];

$result = [];

foreach ($array as $implodedKeys => $value) {
    $keys = array_reverse(explode(';', $implodedKeys));
    $tmp = $value;
    foreach ($keys as $key) {
        $tmp = [$key => $tmp];
    }
    $result = array_merge_recursive($result, $tmp);
}
var_dump($result);

Some explanation: First iterate over array you given, explode keys from each row and reverse them. Now we can iterate over these keys and build each array from inside to outside. At last you can merge it with result recursively. It's not most efficient solution but show there're plenty ways to solve problem

Kamil Karkus
  • 1,283
  • 1
  • 11
  • 29