-2

I'm struggeling second day with transforming dot to tree structure. Can anyone help?

    $input = [
        'inbox'               => ['name' => 'Inbox'],
        'inbox.first'         => ['name' => 'First'],
        'inbox.second'        => ['name' => 'Second'],
        'inbox.second.other'  => ['name' => 'Second Other'],
        'inbox.third.another' => ['name' => 'Third Another'],
    ];

    $expectedOutput = [
        'inbox' => [
            'name'       => 'Inbox',
            'mailbox'    => 'inbox',
            'subfolders' => [
                'first'  => [
                    'name'       => 'First',
                    'mailbox'    => 'inbox.first',
                    'subfolders' => [],
                ],
                'second' => [
                    'name'       => 'Second',
                    'mailbox'    => 'inbox.second',
                    'subfolders' => [
                        'other' => [
                            'name'       => 'Second Other',
                            'subfolders' => [],
                            'mailbox'    => 'inbox.second.other',
                        ],
                    ],
                ],
                'third'  => [
                    'subfolders' => [
                        'another' => [
                            'name'       => 'Third Another',
                            'subfolders' => [],
                            'mailbox'    => 'inbox.third.another',
                        ],
                    ],
                ],
            ],
        ],
    ];
piernik
  • 3,507
  • 3
  • 42
  • 84
  • https://stackoverflow.com/questions/9635968/convert-dot-syntax-like-this-that-other-to-multi-dimensional-array-in-php – Taha Paksu Nov 07 '17 at 09:18
  • Then you'd append the other stuff to that array. – Taha Paksu Nov 07 '17 at 09:19
  • 1
    Possible duplicate of [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) – Justinas Nov 07 '17 at 09:19
  • I saw that anwser - problem is that it has 'subfolders' key and then keys from original array :/ – piernik Nov 07 '17 at 09:21

1 Answers1

1

You can check the laravel function Arr::set as a basis. If you bring your array to a format that matches the output of that function you can use it like so:

 //This is the set function from https://github.com/laravel/framework/blob/5.5/src/Illuminate/Support/Arr.php#L510
function set(&$array, $key, $value)
{
    if (is_null($key)) {
        return $array = $value;
    }
    $keys = explode('.', $key);
    while (count($keys) > 1) {
        $key = array_shift($keys);
        // If the key doesn't exist at this depth, we will just create an empty array
        // to hold the next value, allowing us to create the arrays to hold final
        // values at the correct depth. Then we'll keep digging into the array.
        if (! isset($array[$key]) || ! is_array($array[$key])) {
            $array[$key] = [];
        }
        $array = &$array[$key];
    }
    $array[array_shift($keys)] = $value;
    return $array;
}


$input = [
        'inbox'               => ['name' => 'Inbox'],
        'inbox.first'         => ['name' => 'First'],
        'inbox.second'        => ['name' => 'Second'],
        'inbox.second.other'  => ['name' => 'Second Other'],
        'inbox.third.another' => ['name' => 'Third Another'],
];

$newKeys = array_map(function ($key) {
    $k = explode(".",$key);
    $newkey = [];
    foreach ($k as $segment) {
        $newkey[] = $segment;
        $newkey[] = "subfolders";
    }
    return implode(".",$newkey);
}, array_keys($input)); 

$input = array_combine($newKeys, array_map(function ($value,$key) {
    return array_merge($value, ["mailbox"=>$key]);
},$input,array_keys($input)));

$res = [];
array_walk($input, function ($value,$key) use (&$res) {
    set($res,$key,$value);
});

Demo: http://sandbox.onlinephpfunctions.com/code/9717e7606f099f1352a559c447b5225dd0d74f6c

apokryfos
  • 38,771
  • 9
  • 70
  • 114