2

There is a PHP array like this

Array
(
    [Name/First] => John
    [Name/Last] => Doe
    [Age] => 20
    [Address/Postal/City] => New York
    [Address/Postal/Zip] => 10003
    [Address/Billing/City] => Los Angeles
    [Phone] => 123456789
    [Foo/Bar/Foo2/Bar2] => test
)

I want to build a multidimensional array from that based on the keys exploded by some divider character like /

The expected result is like this:

Array
(
    [Name] => Array
        (
            [First] => John
            [Last] => Doe
        )

    [Age] => 20
    [Address] => Array
        (
            [Postal] => Array
                (
                    [City] => New York
                    [Zip] => 10003
                )

            [Billing] => Array
                (
                    [City] => Los Angeles
                )
        )

    [Phone] => 123456789
    [Foo] => Array
        (
            [Bar] => Array
                (
                    [Foo2] => Array
                        (
                            [Bar2] => test
                        )
                )
        )
)

Should I use some recursive functions for that?

  • What did you try so far? Where are you stuck? – Nico Haase Nov 26 '21 at 10:43
  • Does this answer your question? [Convert dot syntax like "this.that.other" to multi-dimensional array in PHP](https://stackoverflow.com/questions/9635968/convert-dot-syntax-like-this-that-other-to-multi-dimensional-array-in-php) – Matt Raines Dec 06 '21 at 17:14

2 Answers2

1

Here is logic:

$array=array
(
    'Name/First' => 'John',
    'Name/Last' => 'Doe',
    'Age' => 20,
    'Address/Postal/City' => 'New York',
    'Address/Postal/Zip' => 10003,
    'Address/Billing/City' => 'Los Angeles',
    'Phone' => 123456789,
    'Foo/Bar/Foo2/Bar2' => 'test'
);

$result=[];
foreach($array as $key=>$new)
{ 
     $exp=explode("/",$key);
     
     if(count($exp)==1)
     { 
          $result[$key]=$new;
     }
     elseif(count($exp)==2)
     { 
          $result[$exp[0]][$exp[1]]=$new;
     }
     elseif(count($exp)==3)
     {
           
          $result[$exp[0]][$exp[1]][$exp[2]]=$new;
           
     }
     elseif(count($exp)==4)
     {
           
          $result[$exp[0]][$exp[1]][$exp[2]][$exp[3]]=$new;
     } 
     
}
echo "<pre>";
print_R($result);
echo "</pre>";
  • Yep, that works for 4 levels but what if we don't know how deep the array should be. Also I'm not sure you shouln't define level3 as empty array before assign level4? Like `$result[$exp[0]][$exp[1]][$exp[2]] = [];` before `$result[$exp[0]][$exp[1]][$exp[2]][$exp[3]]=$new;` – user2409690 Nov 26 '21 at 07:35
  • Please add some explanation to your answer such that others can learn from it – Nico Haase Nov 26 '21 at 10:44
0

You can build a new array by passing the key by reference.

$newarray = [];

foreach($array as $path => $value) {
    $keys = array_filter(explode('/', $path));
    $ref = &$newarray;
    foreach($keys as $level => $key) {
        $ref = &$ref[$key];
    }
    $ref = $value;
}

print_r($newarray);

fiddle

But if scalar values are possible in the array at the upper levels, then you need to decide for yourself what result should be obtained.

'Foo/Bar' => 'test1',
'Foo/Bar/Foo2/Bar2' => 'test2'

For example, you can add additional checks to avoid adding keys below the scalar value.

$newarray = [];

foreach($array as $path => $value) {
    $keys = array_filter(explode('/', $path));
    $ref = &$newarray;
    foreach($keys as $level => $key) {
        if (!array_key_exists($key, $ref)) $ref[$key] = [];
        $ref = &$ref[$key];
        if (isset($ref) && !is_array($ref)) {
            break;
        }
    }
    if (is_array($ref)) {
        $ref = $value;
    }
}

print_r($newarray);

The following structure will be returned here:

[Foo] => Array
        (
            [Bar] => test1
        )

fiddle

id'7238
  • 2,428
  • 1
  • 3
  • 11