Hierarchically group 2d array data by two columns and concatenate third column values in each unique path

38 Views Asked by At

I need to group the data from my 2d array into an associative array of associative arrays where d values are the first level keys, and the s values will become the second level keys, and the i values should be (potentially comma-separated) second level values in their respective group.

Input:

$array = [
    ["d" => "7 Apr 2024", "s" => "pm", "i" => "el"],
    ["d" => "8 Apr 2024", "s" => "am", "i" => "mn"],
    ["d" => "12 Apr 2024", "s" => "pm", "i" => "mr"],
    ["d" => "12 Apr 2024", "s" => "am", "i" => "mr"],
    ["d" => "12 Apr 2024", "s" => "am", "i" => "da"],
    ["d" => "13 Apr 2024", "s" => "pm", "i" => "li"],
    ["d" => "14 Apr 2024", "s" => "am", "i" => "li"],
    ["d" => "15 Apr 2024", "s" => "mid", "i" => "nd"],
    ["d" => "15 Apr 2024", "s" => "pm", "i" => "da"]
]

Desired result:

[
    "7 Apr 2024" => ["pm" => "el"],
    "8 Apr 2024" => ["am" => "mn"],
    "12 Apr 2024" => ["am" => "mr,da", "pm" => "mr"],
    "13 Apr 2024" => ["pm" => "li"],
    "14 Apr 2024" => ["am" => "li"],
    "15 Apr 2024" => ["pm" => "da", "mid" => "nd"]
]

I have tried every version of every foreach loop using if statements, using while statements, and temporary arrays. I am having difficulty combining the second level values when the date is the same.

2

There are 2 best solutions below

0
Anastas Dolushanov On BEST ANSWER

You need to use array_walk on the input array to create the output.

$output = [];

array_walk($array, function ($item) use (&$output) {
    if (array_key_exists($item["d"], $output) && array_key_exists($item["s"],$output[$item["d"]])) {
        $output[$item["d"]][$item["s"]] .= "," . $item["i"];
    } else {
        $output[$item["d"]][$item["s"]] = $item["i"];
    }
});

print_r($output);
1
mickmackusa On

Use the two grouping columns as the first and second levels of your array. If the combination of first two values are not represented in the result array, save it, otherwise append a comma and the new value.

Code: (Demo)

$result = [];
foreach ($array as ['d' => $d, 's' => $s, 'i' => $i]) {
    if (!isset($result[$d][$s])) {
        $result[$d][$s] = $i;
    } else {
        $result[$d][$s] .= ',' . $i;
    }
}
var_export($result);