Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

There are plenty of tips and code examples out there of accessing PHP arrays with dot notation, but I would like to do somewhat the opposite. I would like to take a multidimensional array like this:

$myArray = array(
    'key1' => 'value1',
    'key2' => array(
        'subkey' => 'subkeyval'
    ),
    'key3' => 'value3',
    'key4' => array(
        'subkey4' => array(
            'subsubkey4' => 'subsubkeyval4',
            'subsubkey5' => 'subsubkeyval5',
        ),
        'subkey5' => 'subkeyval5'
    )
);

And turn it into this (likely through some recursive function):

$newArray = array(
    'key1'                    => 'value1',
    'key2.subkey'             => 'subkeyval',
    'key3'                    => 'value3',
    'key4.subkey4.subsubkey4' => 'subsubkeyval4',
    'key4.subkey5.subsubkey5' => 'subsubkeyval5',
    'key4.subkey5'            => 'subkeyval5'
);
share|improve this question
    
I thought array_walk_recursive might be able to help me to build the new keys since it seemed like it could do a lot of the heavy lifting with recursion but it doesn't provide all the keys of the array. For instance, using array_walk_recursive on $myArray (as run through the example function on the PHP documentation page) would only provide me with the keys that don't have array values. I'm continuing to attempt writing my own recursive function with some good old foreach looping but it's been a long day and is hurting my head. I'll continue to go at it and update if I get it (or any closer) –  TheCheese May 3 '12 at 2:58

4 Answers 4

up vote 18 down vote accepted

teh codez

$ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($myArray));
$result = array();
foreach ($ritit as $leafValue) {
    $keys = array();
    foreach (range(0, $ritit->getDepth()) as $depth) {
        $keys[] = $ritit->getSubIterator($depth)->key();
    }
    $result[ join('.', $keys) ] = $leafValue;
}

output

Array
(
    [key1] => value1
    [key2.subkey] => subkeyval
    [key3] => value3
    [key4.subkey4.subsubkey4] => subsubkeyval4
    [key4.subkey4.subsubkey5] => subsubkeyval5
    [key4.subkey5] => subkeyval5
)

demo: http://codepad.org/YiygqxTM

I need to go, but if you need an explanation of that tomorrow, ask me.

share|improve this answer
2  
+1 Nice Answer!... –  Loz Cherone ツ May 3 '12 at 3:00
    
This is a 1000% better answer than I thought I'd find! I haven't played with RecursiveIteratorIterator at all before (but I will now) so it didn't even cross my mind. Very well done! –  TheCheese May 3 '12 at 3:07
1  
So much win! Great solution @rambo –  joseym Sep 21 '12 at 21:28
1  
Now, how about the reverse of this function? –  Petah Jan 13 '13 at 4:36
1  
@Petah, see stackoverflow.com/q/9635968/1388892 @ rambocoder, what is a "ritit"? I mean the word... thx! --> ah, RecursiveITeratorITerator... righty right :) –  Adrian Föder Mar 17 at 10:38

This will handle an arbitrary level of nesting:

<? //PHP 5.4+
$dotFlatten = static function(array $item, $context = '') use (&$dotFlatten){
    $retval = [];
    foreach($item as $key => $value){
        if (\is_array($value) === true){
            foreach($dotFlatten($value, "$context$key.") as $iKey => $iValue){
                $retval[$iKey] = $iValue;
            }
        } else {
            $retval["$context$key"] = $value;
        }
    }
    return $retval;
};

var_dump(
    $dotFlatten(
        [
            'key1' => 'value1',
            'key2' => [
                'subkey' => 'subkeyval',
            ],
            'key3' => 'value3',
            'key4' => [
                'subkey4' => [
                    'subsubkey4' => 'subsubkeyval4',
                    'subsubkey5' => 'subsubkeyval5',
                ],
                'subkey5' => 'subkeyval5',
            ],
        ]
    )
);
?>
share|improve this answer

You could do it like this, but chris's answer should be preferred:

<?php 
$array = array();
foreach($myArray as $key=>$value){
    //1st level
    if(is_array($value)){
        //2nd level
        foreach($value as $key_b=>$value_b){
            //3rd level
            if(is_array($value_b)){
                foreach($value_b as $key_c=>$value_c){
                    $array[$key.'.'.$key_b.'.'.$key_c]=$value_c;
                }
            }else{
                $array[$key.'.'.$key_b]=$value_b;
            }
        }
    }else{
        $array[$key]=$value;
    }
}

print_r($array);
/*
Array
(
[key1] => value1
[key2.subkey] => subkeyval
[key3] => value3
[key4.subkey4.subsubkey4] => subsubkeyval4
[key4.subkey4.subsubkey5] => subsubkeyval5
[key4.subkey5] => subkeyval5
)
*/
share|improve this answer

This is my take on a recursive solution, which works for arrays of any depth:

function convertArray($arr, $narr = array(), $nkey = '') {
    foreach ($arr as $key => $value) {
        if (is_array($value)) {
            $narr = array_merge($narr, convertArray($value, $narr, $nkey . $key . '.'));
        } else {
            $narr[$nkey . $key] = $value;
        }
    }

    return $narr;
}

Which can be called as $newArray = convertArray($myArray).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.