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

5 Answers 5

up vote 26 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!... –  Lawrence 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 '14 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

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

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 another approach similar to Blafrat above - but handles simply arrays as values.

 function dot_flatten($input_arr, $return_arr = array(), $prev_key = '')
 {
     foreach ($input_arr as $key => $value)
     {
        $new_key = $prev_key . $key;

        // check if it's associative array 99% good
        if (is_array($value) && key($value) !==0 && key($value) !==null)
        {
            $return_arr = array_merge($return_arr, dot_flatten($value, $return_arr, $new_key . '.'));
        }
        else
        {
            $return_arr[$new_key] = $value;
        }
    }

    return $return_arr;
}

(The only case this wouldn't catch is where you had a value that was associative but the first key was 0.)

Note that the RecursiveIteratorIterator can be slower than regular recursive function. https://xenforo.com/community/threads/php-spl-why-is-recursiveiteratoriterator-100x-slower-than-recursive-search.57572/

In this case using the sample array given for 1000 iterations php5.6, this code is twice as fast (recursive=.032 vs interator=.062) - but the difference is probably insignificant for most cases. Mainly I prefer recursive because I find the logic of the Iterator needlessly complicated for a simple use case like this.

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.