Skip to content
Advertisement

Group row data within a 2d array based on a single column and push unique data into respective subarrays

I need to group data in a multidimensional array data which can be related on a single column entry_id.

In addition to the entry_id there are other columns that will also be identical in other related rows (ic, name, and residency). While grouping, these data points can simply be overwritten — in other words, I don’t need to collect multiple copies of the same value within the respective group.

Finally, there will be data points within respective groups that will differ — these values need to stored as subarrays within the groups so that no data is lost.

If there is only one row’s data in a group, the file_no and detail data does not need to be converted to an array. This means that the result array will have variable depth — some rows will flat and other may be 2 dimensional.

Sample input:

$array = [
    [
        'entry_id' => 1,
        'ic' => 2147483647,
        'name' => 'Kořínková Blanka',
        'residency' => 'Štětí, Lukešova 354, 411 08',
        'file_no' => 'KSUL 77 INS 18898 / 2013',
        'detail' => '749371da-725c-4738-8def-2f7167142a6f'
    ],
    [
        'entry_id' => 1,
        'ic' => 2147483647,
        'name' => 'Kořínková Blanka',
        'residency' => 'Štětí, Lukešova 354, 411 08',
        'file_no' => 'KSUL 77 INS 21218 / 2013',
        'detail' => '43b6a718-4647-451d-9c53-50dfee8403ff'
    ],
    [
        'entry_id' => 2,
        'ic' => 46900217,
        'name' => 'ENTEC a.s. "v likvidaci"',
        'residency' => 'Staré Město, Brněnská 1916, 686 03',
        'file_no' => 'KSBR 28 INS 1232 / 2013',
        'detail' => 'e2155a52-c464-4357-b71b-4f4ff75585eb'
    ],
];

Desired output (based on same ‘entry_id’ grouping):

Array
(
    [0] => Array
        (
            [entry_id] => 1
            [ic] => 2147483647
            [name] => Kořínková Blanka
            [residency] => Štětí, Lukešova 354, 411 08
            [file_no] => Array
                 (
                       [0] => KSUL 77 INS 18898 / 2013
                       [1] => KSUL 77 INS 21218 / 2013
                 )
            [detail] => Array
                 (
                       [0] => A749371da-725c-4738-8def-2f7167142a6f
                       [1] => 43b6a718-4647-451d-9c53-50dfee8403ff
                 )
        )

    [1] => Array
        (
            [entry_id] => 2
            [ic] => 46900217
            [name] => ENTEC a.s. "v likvidaci"
            [residency] => Staré Město, Brněnská 1916, 686 03
            [file_no] => KSBR 28 INS 1232 / 2013
            [detail] => e2155a52-c464-4357-b71b-4f4ff75585eb
        )
)

Advertisement

Answer

Your issue can be resolved with one functional block, using array_reduce() and array_merge() principles:

$mergeId = 'entry_id';

$data = array_reduce($data, function($c, $x) use ($mergeId)
{
   $c[$x[$mergeId]] = isset($c[$x[$mergeId]])
      ?array_combine(
          $z=array_keys($c[$x[$mergeId]]), 
          array_map(function($y) use ($x, $c, $mergeId)
          {
             return in_array($x[$y], (array)$c[$x[$mergeId]][$y])
                ?$c[$x[$mergeId]][$y]
                :array_merge((array)$c[$x[$mergeId]][$y], [$x[$y]]);
          }, $z)
       )
      :$x;
   return $c;
}, []);

you may want to apply array_values() if you need to re-index result set (so keys would be consecutive, starting from 0). Check the fiddle.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement