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

4

14

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',
        ]
    ]
]
Picklock answered 24/8, 2012 at 11:30 Comment(0)
R
33

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)
Reddish answered 24/8, 2012 at 11:47 Comment(1)
This answer is missing its educational explanation.Cahan
R
6
<?php

$grouped_types = array();

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

?>
Renayrenckens answered 24/8, 2012 at 11:35 Comment(1)
This answer is provably incorrect. It doesn't not return the desired output. 3v4l.org/LGKbg Please always explain your snippets when posting on Stack Overflow.Cahan
C
1

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));
Cahan answered 28/7, 2022 at 13:3 Comment(0)
B
-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',
    ),
  ),
)
Bishop answered 28/7, 2022 at 11:59 Comment(3)
This unexplained answer saved your day? Hmm... where have I seen that $compositeKey variable name recently. 1, 2 Please never post code-only answers on Stack Overflow. Every answer should contain an educational explanation with the intent to empower the asker and thousands of future researchers.Cahan
Your copy-pasta of my snippet to a similar question doesn't make sense. You are accessing a single value and calling it a $compositeKey. This indicates that you didn't actually understand what my snippet was doing or why the variable was declared.Cahan
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Past

© 2022 - 2024 — McMap. All rights reserved.