HartleySan
HartleySan

Reputation: 7810

How do I make this flat array hierarchical in PHP without parent IDs?

I have a flat array structure ($rows) with an array of columns ($groupByCols) that I want to group the data by:

$groupByCols = ['a', 'b'];
$rows = [
    [
        'a' => 1,
        'b' => 10,
        'c' => 100
    ],
    [
        'a' => 1,
        'b' => 20,
        'c' => 200
    ],
    [
        'a' => 1,
        'b' => 20,
        'c' => 300
    ],
    [
        'a' => 1,
        'b' => 30,
        'c' => 400
    ],
    [
        'a' => 2,
        'b' => 40,
        'c' => 500
    ],
    [
        'a' => 2,
        'b' => 50,
        'c' => 600
    ],
    [
        'a' => 3,
        'b' => 60,
        'c' => 700
    ]
];

By looping through the $rows variable and referencing each of the $groupByCols values in order, I want to get the following hierarchical array:

$groupedRows = [
    [
        [
            [
                'a' => 1,
                'b' => 10,
                'c' => 100
            ]
        ],
        [
            [
                'a' => 1,
                'b' => 20,
                'c' => 200
            ],
            [
                'a' => 1,
                'b' => 20,
                'c' => 300
            ]
        ],
        [
            [
                'a' => 1,
                'b' => 30,
                'c' => 400
            ]
        ]
    ],
    [
        [
            [
                'a' => 2,
                'b' => 40,
                'c' => 500
            ]
        ],
        [
            [
                'a' => 2,
                'b' => 50,
                'c' => 600
            ]
        ]
    ],
    [
        [
            [
                'a' => 3,
                'b' => 60,
                'c' => 700
            ]
        ]
    ]
];

I'm 99% sure that I need to use recursion for this, but after trying about 10 different things (none of which worked), I can't figure out how to get what I want.

Normally, I would share code I've written thus far, but after thinking about this for several days and not getting anywhere, I really don't have much to show.

I think I just need some general guidance on how I can (assumingly) recursively use the $groupByCols and $rows variables to get the $groupedRows array. Any assistance would be greatly appreciated.

Also, please note that the data above is very simple for demonstration purposes. The real data can be infinity longer and more complex, and I may have to go down 5-6 levels with the $groupByCols, depending on the nature of what's required.

Thank you.

Upvotes: 0

Views: 47

Answers (1)

Nick
Nick

Reputation: 147146

This function will do what you want. It goes through the array, grouping by the values indexed by the first value in $columns. If there are columns remaining in the $columns array, it recursively groups by those columns. To avoid having oddly numbered keys, it calls array_values to reindex the result to numeric keys starting at 0.

function group_by($array, $columns) {
    $new_arr = array();
    $column = array_shift($columns);
    foreach ($array as $arr) {
        $new_arr[$arr[$column]][] = $arr;
    }
    if (count($columns)) {
        foreach ($new_arr as &$arr) {
            $arr = group_by($arr, $columns);
        }
    }
    return array_values($new_arr);
}
print_r(group_by($rows, $groupByCols));

Output is as you desire, but rather than clutter the answer with a long print, just see the demo on 3v4l.org.

Upvotes: 1

Related Questions