-1

i need help to find best practice answer for current code. ill be thankful for you help.

how can i loop through this array in the best way:

$data = [
    'element1.child.property1'  => 1,
    'element1.child.property2'  => 2,
    'element2.child.name'       => 3,
    'element2.child2.name'      => 4,
    'element2.child2.position'  => 5,
    'element3.child3.position'  => 6,
];

to get answer like that

$result = [
    'element1' => [
        'child' => [
            'property1' => 1,
            'property2' => 2,
        ]
    ],
    'element2' => [
        'child' => [
            'name' => 3
        ],
        'child2' => [
            'name' => 4,
            'position' => 5
        ]
    ],
    'element3' => [
        'child3' => [
            'position' => 6
        ]
    ],
];
E.M
  • 1
  • 2
  • Ok, but show us what you have tried do far, show us your code – RiggsFolly Apr 03 '18 at 15:10
  • 1
    There is no ___Best Practice way___, there is just the way you can come up with and code. Thats just an excuse for _I have not tried to do this for myself, I want someone else to write this_ – RiggsFolly Apr 03 '18 at 15:13

3 Answers3

1

You can loop through the array and explode the key of each element by ".", and then populate your new array:

<?php

$data = [
    'element1.child.property1'  => 1,
    'element1.child.property2'  => 2,
    'element2.child.name'       => 3,
    'element2.child2.name'      => 4,
    'element2.child2.position'  => 5,
    'element3.child3.position'  => 6,
];

foreach ($data as $key => $value) {
    $key = explode(".", $key);
    $newData[$key[0]][$key[1]][$key[2]] = $value;
}

print_r($newData);
?>

Which gives you this:

Array
    (
    [element1] => Array
        (
            [child] => Array
                (
                    [property1] => 1
                    [property2] => 2
                )

        )

    [element2] => Array
        (
            [child] => Array
                (
                    [name] => 3
                )

            [child2] => Array
                (
                    [name] => 4
                    [position] => 5
                )

        )

    [element3] => Array
        (
            [child3] => Array
                (
                    [position] => 6
                )

        )

)
Ryan Wright
  • 177
  • 1
  • 10
1

Here is your array :

$data = [
    'element1.child.property1'  => 1,
    'element1.child.property2'  => 2,
    'element2.child.name'       => 3,
    'element2.child2.name'      => 4,
    'element2.child2.position'  => 5,
    'element3.child3.position'  => 6,
];

1/ First, create a result array :

$result = array();

2/ Then you will loop through your array and build the desired output:

foreach ($data as $key => $value) {
    $elt = explode(".", $key);

    // Here you will have :
    // $elt[0] = "elementX";
    // $elt[1] = "child";
    // $elt[2] = "property1"; (OR "name" OR "position"...)


    $result[$elt[0]][$elt[1]][$elt[2]] = $value;
}

3/ Now if you look the result he looks like the output you want:

var_dump($result);

$result = [
    'element1' => [
        'child' => [
            'property1' => 1,
            'property2' => 2,
        ]
    ],
    'element2' => [
        'child' => [
            'name' => 3
        ],
        'child2' => [
            'name' => 4,
            'position' => 5
        ]
    ],
    'element3' => [
        'child3' => [
            'position' => 6
        ]
    ],
];

Hope it helps

Mickaël Leger
  • 3,426
  • 2
  • 17
  • 36
  • This works for the example data but not `aaa.bbbb.cccc.dddd`. – AbraCadaver Apr 03 '18 at 15:29
  • You lost me with the duplication part. You can't have 2 same keys in the start data anyway. – oliver de Cramer Apr 03 '18 at 15:29
  • @oliverdeCramer I deleted this part, you are 100% right that he CAN'T have duplicate, my bad – Mickaël Leger Apr 03 '18 at 15:30
  • @AbraCadaver You're right, but in OP example I can't know if he can have more than 3 "elt". Should I try to edit my anwser? – Mickaël Leger Apr 03 '18 at 15:32
  • @AbraCadaver Again, I'm 100% ok with you but OP array has only 3 words as key so...this solution is adapted to THIS array but not for all case, I will see if I can update it to works for `aaa.bbb.ccc.ddd` too – Mickaël Leger Apr 03 '18 at 15:37
  • @oliverdeCramer: Not duplicate in start data but duplicate of part: `element1.child.property1.val => 9` would overwrite `element1.child.property1 => 1` with an array `val => 9`. – AbraCadaver Apr 03 '18 at 15:40
1

More dynamic for variable lengths and deeper or shallower nesting. You can use this function and loop your array using the keys as the path and value as the value. Result will be in $result:

function set($path, &$array=array(), $value=null) {
    $path = explode('.', $path);
    $temp =& $array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    $temp = $value;
}

foreach($data as $path => $value) {
    set($path, $result, $value);
}

See How to access and manipulate multi-dimensional array by key names / path? for other uses.

AbraCadaver
  • 78,200
  • 7
  • 66
  • 87