3

I need to group rows in my two-dimensional array by two columns then within each group, I need to join another column's values with commas.

Notice that in the third row, the diagnostic value is empty.

$data = [
  ["id" => 1, "begin" => "01/01", "diagnostic" => "a"],
  ["id" => 1, "begin" => "01/01", "diagnostic" => "b"],
  ["id" => 1, "begin" => "01/01", "diagnostic" => ""],
  ["id" => 1, "begin" => "02/02", "diagnostic" => "a"],
];

Expected result:

[
  ["id" => 1, "begin" => "01/01", "diagnostic" => "a, b"],
  ["id" => 1, "begin" => "02/02", "diagnostic" => "a"],
]
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
m4gn4n
  • 31
  • 2

2 Answers2

0

To be fair, you are asking for a complete solution.

So here's my quick take on how to get it done:

http://sandbox.onlinephpfunctions.com/code/eb4fef6146b77fb7ff157790046c79750ef90cdb

<?php
$data = [
  0 =>array("id"=>1, "begin"=>"01/01","diagnostic"=>"a", "procedure" => "x"),
  1 =>array("id"=>1, "begin"=>"01/01","diagnostic"=>"b", "procedure" => ""),
  2 =>array("id"=>1, "begin"=>"01/01","diagnostic"=>"a", "procedure" => "y"),
  3 =>array("id"=>1, "begin"=>"02/02","diagnostic"=>"a", "procedure" => "z"),
];

// create an empty array to hold results
$result = [];

// iterate through each entry of the original $data
foreach($data as $entry){
    // create a temporary array index, that will be unique across the entries conditions (begin, id)
    $tempId = $entry['id'] . '-' . $entry['begin'];

    // create and append entries to diagnostic and procedure
    $result[$tempId]['diagnostic'][] = $entry['diagnostic'];
    $result[$tempId]['procedure'][] = $entry['procedure'];

    // copy data that is identical
    $result[$tempId]['begin'] = $entry['begin'];
    $result[$tempId]['id'] = $entry['id'];
}

// iterate through entries and implode unique, not empty elements of diagnostic and procedure array with a comma
foreach($result as &$entry){
    $entry['diagnostic'] = implode(',', array_unique(array_filter($entry['diagnostic'])));
    $entry['procedure'] = implode(',', array_unique(array_filter($entry['procedure'])));
}
print_r($result);

The above will produce:

Array
(
    [1-01/01] => Array
        (
            [diagnostic] => a,b
            [procedure] => x,y
            [begin] => 01/01
            [id] => 1
        )

    [1-02/02] => Array
        (
            [diagnostic] => a
            [procedure] => z
            [begin] => 02/02
            [id] => 1
        )

)
Unamata Sanatarai
  • 6,475
  • 3
  • 29
  • 51
0

This task has a slight twist compared to the usual "group and append/concat" questions because you want to avoid writing unnecessary commas when an empty diagnostic value exists in a group. The classic (best) approach is to use the two identifying row values to form a unique string and apply that string as the first level "grouping key" in the result array.

Every time a combination of id and begin values is encountered, the row data needs to be pushed into the group and correctly formatted.

The extra step, here, is that you must check the length of the current diagnostic value AND check the length of the group's diagnostic value to determine if a comma needs to be appended before the new value.

It doesn't take much imagination to understand that using a single loop is going to outperform using multiple loops and array_column() calls.

Code: (Demo)

$result = [];
foreach ($data as $row) {
    $compositeKey = $row['id'] . '-' . $row['begin'];
    if (!isset($result[$compositeKey])) {
        $result[$compositeKey] = $row;
    } elseif (strlen($row['diagnostic'])) {
        $result[$compositeKey]['diagnostic'] .= (strlen($result[$compositeKey]['diagnostic']) ? ', ' : '') . $row['diagnostic'];
    }
}
var_export(array_values($result));

Output:

array (
  0 => 
  array (
    'id' => 1,
    'begin' => '01/01',
    'diagnostic' => 'a, b',
  ),
  1 => 
  array (
    'id' => 1,
    'begin' => '02/02',
    'diagnostic' => 'a',
  ),
)
mickmackusa
  • 43,625
  • 12
  • 83
  • 136