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',
        ]
    ]
]
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
408
  • 161
  • 1
  • 1
  • 4

4 Answers4

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)
Anthony Simmon
  • 1,579
  • 12
  • 26
6
<?php

$grouped_types = array();

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

?>
Wayne Whitty
  • 19,513
  • 7
  • 44
  • 66
  • This answer is provably incorrect. It doesn't not return the desired output. https://3v4l.org/LGKbg Please always explain your snippets when posting on Stack Overflow. – mickmackusa Jul 28 '22 at 12:45
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));
Dharman
  • 30,962
  • 25
  • 85
  • 135
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
-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',
    ),
  ),
)
Dharman
  • 30,962
  • 25
  • 85
  • 135
  • This unexplained answer saved your day? Hmm... where have I seen that `$compositeKey` variable name recently. [1](https://stackoverflow.com/a/73149340/2943403), [2](https://stackoverflow.com/a/73148789/2943403) 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. – mickmackusa Jul 28 '22 at 12:40
  • 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. – mickmackusa Jul 28 '22 at 12:48
  • 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](/help/how-to-answer). – Community Jul 31 '22 at 03:20