408
408

Reputation: 161

Group row data by one column value and populate a subarray in each group with the other column value

I want to group the data in an array with associative rows. Group should be determined by the type value and all label_id values within each group should be formed into a subarray.

Sample input:

$array = [
    ['type' => 'AAA', 'label_id' => 'A1,35'],
    ['type' => 'AAA', 'label_id' => 'A2,34'],
    ['type' => 'BBB', 'label_id' => 'B1,29'],
    ['type' => 'CCC', 'label_id' => 'C1,20'],
    ['type' => 'CCC', 'label_id' => 'C2,19'],
    ['type' => 'CCC', 'label_id' => 'C3,18']
];

The desired result:

[
    [
        'type' => 'AAA',
        'label_id' => [
            'A1,35',
            'A2,34'
        ],
    [
        'type' => 'BBB',
        'label_id' => [
            'B1,29'
        ],
    ],
    [
        'type' => 'CCC',
        'label_id' => [
            'C1,20',
            'C2,19',
            'C3,18',
        ]
    ]
]

Upvotes: 14

Views: 39259

Answers (4)

vishal wayachal
vishal wayachal

Reputation: 1

$args = array(
    array('type' => 'AAA', 'label_id' => 'A1,35'),
    array('type' => 'AAA', 'label_id' => 'A2,34'),
    array('type' => 'BBB', 'label_id' => 'B1,29'),
    array('type' => 'CCC', 'label_id' => 'C1,20'),
    array('type' => 'CCC', 'label_id' => 'C2,19'),
    array('type' => 'CCC', 'label_id' => 'C3,18')
);

$result = [];
foreach ($args as $row) {
    $compositeKey = $row['type'];
    $result[$compositeKey] = [
        'type' => $row['type'],
        'label_id' => array_merge($result[$compositeKey]['label_id'] ?? [], [
            $row['label_id']
        ])
    ];
}
print_r(array_values($result));

Output:

array (
  0 =>
  array (
    'type' => 'AAA',
    'label_id' =>
    array (
      0 => 'A1,35',
      1 => 'A2,34',
    ),
  ),
  1 =>
  array (
    'type' => 'BBB',
    'label_id' =>
    array (
      0 => 'B1,29',
    ),
  ),
  2 =>
  array (
    'type' => 'CCC',
    'label_id' =>
    array (
      0 => 'C1,20',
      1 => 'C2,19',
      2 => 'C3,18',
    ),
  ),
)

Upvotes: -1

mickmackusa
mickmackusa

Reputation: 47894

This task can be and should be completed with a single loop.

Use the type values as temporary grouping keys while you store respective row data. The null coalescing assignment operator (??=) isn't essential (it could be = and keep overwriting the same value each time), but it endeavors to prevent the re-writing of an identical value over the cached value.

Push label_id values into the subarray of each respective group. Re-index the array when the loop is finished.

Code: (Demo)

$result = [];
foreach ($array as $row) {
    $result[$row['type']]['type'] ??= $row['type'];
    $result[$row['type']]['label_id'][] = $row['label_id'];
}
var_export(array_values($result));

For a functional coding style, use array_reduce() with the same body as the previous snippet. array_reduce() is appropriate when it is possible that the number of elements in the result may differ from the number of elements in the input array. (Demo)

var_export(
    array_values(
        array_reduce(
            $array,
            function($result, $row) {
                $result[$row['type']]['type'] ??= $row['type'];
                $result[$row['type']]['label_id'][] = $row['label_id'];
                return $result;
            },
            []
        )
    )
);

If you want to get funky (unprofessional) with it, you can write a body-less loop with the same functionality/output. (Demo)

$result = [];
foreach ($array as [
    'type' => $type,
    'label_id' => $id,
    'type' => $result[$type]['type'], 
    'label_id' => $result[$type]['label_id'][]
]);
var_export(array_values($result));

Upvotes: 1

Anthony Simmon
Anthony Simmon

Reputation: 1607

This should do the trick

$args = array
(
    array( 'type' => 'AAA', 'label_id' => 'A1,35' ),
    array( 'type' => 'AAA', 'label_id' => 'A2,34' ),
    array( 'type' => 'BBB', 'label_id' => 'B1,29' ),
    array( 'type' => 'CCC', 'label_id' => 'C1,20' ),
    array( 'type' => 'CCC', 'label_id' => 'C2,19' ),
    array( 'type' => 'CCC', 'label_id' => 'C3,18' )  
);

$tmp = array();

foreach($args as $arg)
{
    $tmp[$arg['type']][] = $arg['label_id'];
}

$output = array();

foreach($tmp as $type => $labels)
{
    $output[] = array(
        'type' => $type,
        'label_id' => $labels
    );
}

var_dump($output);

The output is :

array
  0 => 
    array
      'type' => string 'AAA' (length=3)
      'label_id' => 
        array
          0 => string 'A1,35' (length=5)
          1 => string 'A2,34' (length=5)
  1 => 
    array
      'type' => string 'BBB' (length=3)
      'label_id' => 
        array
          0 => string 'B1,29' (length=5)
  2 => 
    array
      'type' => string 'CCC' (length=3)
      'label_id' => 
        array
          0 => string 'C1,20' (length=5)
          1 => string 'C2,19' (length=5)
          2 => string 'C3,18' (length=5)

Upvotes: 33

user399666
user399666

Reputation: 19879

<?php

$grouped_types = array();

foreach($types as $type){
        $grouped_types[$type['type']][] = $type;
}

?>

Upvotes: 6

Related Questions