Search code examples
phparraysmultidimensional-arraykeypaths

Convert a flat associative array with delimited keypaths as keys into a multidimensional associative array


I have an array with keys that describe location in a multidimensional array like:

array(
        '3728:baskets:4839:1' => 'apple',
        '3728:baskets:4839:2' => 'orange',
        '3728:baskets:4920:1' => 'cherry',
        '3728:baskets:4920:2' => 'apple',
        '9583:baskets:4729:1' => 'pear',
        '9583:baskets:4729:2' => 'orange',
        '9583:baskets:6827:1' => 'banana',
        '9583:baskets:6827:2' => 'pineapple',
);

I would like to pass this array to a function that generates a multidimensional array based on the the pieces in the keys delimited by the ":". The resulting array should look like:

array(
    3728 => array(
        'baskets' => array(
            4839 => array(
                1 => 'apple',
                2 => 'orange',
            ),
            4920 => array(
                1 => 'cherry',
                2 => 'apple',
            ),
        ),
    ),
    9583 => array(
        'baskets' => array(
            4729 => array(
                1 => 'pear',
                2 => 'orange',
            ),
            6827 => array(
                1 => 'banana',
                2 => 'pineapple',
            ),
        ),
    ),
);

Solution

  • function array_createmulti($arr) {
        // The new multidimensional array we will return
        $result = array();
        // Process each item of the input array
        foreach ($arr as $key => $value) {
            // Store a reference to the root of the array
            $current = &$result;
            // Split up the current item's key into its pieces
            $pieces = explode(':', $key);
            // For all but the last piece of the key, create a new sub-array (if
            // necessary), and update the $current variable to a reference of that
            // sub-array
            for ($i = 0; $i < count($pieces) - 1; $i++) {
                $step = $pieces[$i];
                if (!isset($current[$step])) {
                    $current[$step] = array();
                }
                $current = &$current[$step];
            }
            // Add the current value into the final nested sub-array
            $current[$pieces[$i]] = $value;
        }
        // Return the result array
        return $result;
    }