Search code examples
phparraysrecursionmultidimensional-arrayflatten

Replace multidimensional rows with key-value pairs from each of its leafnodes


I want to flatten an array of row -- each with variable depth -- so that it becomes an array of associative arrays.

I tried some very good examples over here that works for associative or multi dimensional arrays but couldn't put them together in a good use to solve my problem:

Array
(
    [0] => Array
        (
            [level2_1] => aa
            [level2_2] => bb
            [level2_3] => cc
            [level2_4] => Array
                (
                    [level3_1] => DDD
                    [level3_2] => EEE
                )

        )

    [1] => Array
        (
            [level2_1] => ff
            [level2_2] => gg
            [level2_3] => hh
            [level2_4] => Array
                (
                    [level3_1] => III
                    [level3_2] => JJJ
                )

        )

)

Expected output:

0 -> level2_1: aa, level2_2: bb, level2_3: cc, level3_1: DDD, level3_2: EEE
1 -> level2_1: ff, level2_2: gg, level2_3: hh, level3_1: III, level3_2: JJJ

Or At Least:

0: aa, bb, cc, DDD, EEE
1: ff, gg, hh, III, JJJ

I tried many non-loop answers regarding implode, multi-dimension, etc. I think they need some modification if one of the element (level2_4) is array instead of string, flatten its elements.

Here are some good samples of code I found working but needs to be modified to fit my case:

# Basic but stops at a sub-array:

echo implode(',', call_user_func_array('array_merge', $data));

# PHP implode associative array:

implode(', ', array_map(function ($k, $v) { return "$k: $v"; }, array_keys($data), array_values($data)));

# PHP implode multi dimensional array:

$result[0][code] = "123";

$result[0][desc] = "Desc123";

$result[1][code] = "567";

$result[1][desc] = "Desc567";

echo implode(', ', array_map(function ($k, $v) { return "$k: $v"; }, array_keys(array_column($result, 'desc', 'code')), array_values(array_column($result, 'desc', 'code'))));


Solution

  • With combination of array_keys + array_walk_recursive + array_map functions:

    // $arr is your initial array
    $result = array_map(function($k) use($arr){
        $s = "$k ->";   // key prefix
        array_walk_recursive($arr[$k], function($v, $k) use(&$s){
            $s .= " $k: $v,";
        });
        return trim($s, ',');
    }, array_keys($arr));
    
    print_r($result);
    

    The output:

    Array
    (
        [0] => 0 -> level2_1: aa, level2_2: bb, level2_3: cc, level3_1: DDD, level3_2: EEE
        [1] => 1 -> level2_1: ff, level2_2: gg, level2_3: hh, level3_1: III, level3_2: JJJ
    )