user431806
user431806

Reputation: 416

Group recurring values from a flat array into their own respective subarrays

I have an array that that I would like convert to a 2d array by grouping identical values together.

Once all elements with the same values have been pushed into the group, I want to use that group for something, then continue the loop and setup the next group, until all content of the original $array has been used.

public function adjust($array){ 
  // $array = [1, 1, 2, 2, 8, 8, 8, 9, 20]
 
  $group = array()

  for ($i = 0; $i < sizeof($array); $i++){
   // code here
   // result should be $group = [1, 1] 
   // use $group for something, reset its contents, 
   // continue loop until group is [2, 2],
   // rinse and repeat
 }    
}

I don't necesarrily need a loop, I just require to be able to slice $array into 5 $groups (for this specific example), to be able to process the data.

Is there an easier way to solve this without a bunch of if/else conditions?

Upvotes: 0

Views: 1935

Answers (3)

mickmackusa
mickmackusa

Reputation: 47904

This can be done without any conditions and without pre-grouping with array_count_values(). No iterated function calls are necessary. Just use each value as a temporary grouping key as you push each value into their own dedicated subarray. This technique will group values even if recurring values are not consecutive. If you want to remove the temporary keys, just call array_values().

Language Construct Loop: (Demo)

$result = [];
foreach ($array as $value) {
    $result[$value][] = $value;
}
var_export(array_values($result));

Functional Loop: (Demo)

var_export(
    array_values(
        array_reduce(
            $array,
            function($result, $value) {
                $result[$value][] = $value;
                return $result;
            },
            []
        )
    )
);

Both output the following data structure:

[[1, 1], [2, 2], [8, 8, 8], [9], [20]]

Upvotes: 0

Barmar
Barmar

Reputation: 781068

Initialize $chunk to an array containing the first element. Then loop through the rest of the array, comparing the current element to what's in $chunk. If it's different, process $chunk and reset it.

$chunk = array[$array[0]];
for ($i = 1; $i < count($array); $i++) {
    if ($array[$i] != $chunk[0]) {
        // use $chunk for something
        $chunk = array($array[$i]);
    } else {
        $chunk[] = $array[$i];
    }
}
// process the last $chunk here when loop is done

Upvotes: 1

Federkun
Federkun

Reputation: 36944

array_count_values is more or likely what you want.

$array = [1, 1, 2, 2, 8, 8, 8, 9, 20];
foreach (array_count_values($array) as $val => $count) {
    $chunk = array_fill(0, $count, $val); // contains [1, 1], [2, 2], etc.
}

Upvotes: 0

Related Questions