2

I have an array that looks something like this:

array:2 [
    "test1_test2_test3" => "result"
    "category_slug" => "the_slug"
]

What I need to do is convert it to a multidimensional array that would look something like this:

array:2 [
    "test1" => [
        "test2" => [
            "test3" => "result"
        ]
    ]
    "category" => [
        "slug" => "the_slug"
    ]
]

I know that I can explode on the key to get an array but am unsure of how to then go from this to end up with the final result.

EDIT The array looks like that initially because it's being pulled from request parameters: http://url.com?test1.test2.test3=result&category.slug=the_slug and Laravel auto converts it to an array.

  • Wouldn't it be better to create the array in the way you later want to use it? – RiggsFolly Feb 24 '18 at 23:30
  • 1
    Dupe: https://stackoverflow.com/a/37356543/3392762 – Progrock Feb 25 '18 at 00:06
  • Possible duplicate of [PHP explode string key into multidimensional array with values](https://stackoverflow.com/questions/37356391/php-explode-string-key-into-multidimensional-array-with-values) – Aken Roberts Feb 25 '18 at 00:30

4 Answers4

1

A simple solution:

$result = [];
foreach ($array as $key => $value) {
    foreach (array_reverse(explode('_', $key)) as $key_part) {
        $value = [$key_part => $value];
    }
    $result += $value;
}

If you need to handle several keys with the same parts (such as test1_test2_test3 and test1_test2_test4), replace the last line with:

$result = array_merge_recursive($result, $value);

Jeto
  • 14,596
  • 2
  • 32
  • 46
0

My approach would be to reverse the array, then loop through the keys and nest them.

The code below should do the trick.

$array = [
    "test1_test2_test3" => "result",
    "category_slug" => "the_slug"
];

$array = array_map(function ($key, $value) {
    $keys = array_reverse(explode('_', $key));
    while($key = array_shift($keys)) {
        $value = [$key => $value];
    }

    return $value;
}, array_keys($array), $array);

$array = call_user_func_array('array_merge', $array);
var_dump($array);

/**
array(2) {
    ["test1"]=>
    array(1) {
        ["test2"]=>
        array(1) {
            ["test3"]=>
            string(6) "result"
        }
    }
    ["category"]=>
    array(1) {
        ["slug"]=>
        string(8) "the_slug"
    }
}
*/
Jordi Kroon
  • 2,607
  • 3
  • 31
  • 55
0

One way to go:

$arr = array("test1_test2_test3" => "result", "category_slug" => "the_slug");
$res = array();

foreach($arr as $k=>$v) {

        $t = explode("_", $k);
        $new_arr = array();
        $tmp = $v; 
        for($i=count($t)-1; $i > 0; $i--) {
                $new_arr[$t[$i]] = $tmp;
                $tmp = $new_arr;
                $new_arr = array();
        }

        $res[$t[0]] = $tmp;

}

print_r($res);

Result:

Array
(
    [test1] => Array
        (
            [test2] => Array
                (
                    [test3] => result
                )

        )

    [category] => Array
        (
            [slug] => the_slug
        )

)
man0v
  • 654
  • 3
  • 13
0

Looking through the Laravel documentation I found a helper array_set, which means in order to change the key to a multidimensional array I can change the key to use dot notation with str_replace and then use the helper to convert it over:

$array = [
    "test1_test2_test3" => "result"
    "category_slug" => "the_slug"
]

$new_array = []

foreach($array as $key => $value)
{
    $key = str_replace('_', '.', $key);
    array_set($new_array, $key, $value);
}

Result:

array:2 [
    "test1" => [
        "test2" => [
            "test3" => "result"
        ]
    ]
    "category" => [
        "slug" => "the_slug"
    ]
]