Skip to content

Instantly share code, notes, and snippets.

@T99
Created December 12, 2022 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save T99/45fe3b5fce7d10a06c1da9ad0a27d005 to your computer and use it in GitHub Desktop.
Save T99/45fe3b5fce7d10a06c1da9ad0a27d005 to your computer and use it in GitHub Desktop.
Group a given input array using a configurable set of fields.
<?php
/**
* Given a 2-dimensional array, this function returns a mapped 2-dimensional
* array wherein the rows of the input array have been 'grouped'.
*
* 'Grouping' involves merging similar rows of the input array. Rows are
* considered 'similar' if some subset of their fields are found to be
* equivalent to each other. This subset of fields is identified using the
* '$group_by' argument. 'Merging' involves the creation of an array of the
* values of similar rows, wherein this array of similar rows is substituted in
* as the value of the field from which the array was created for the 'grouped'
* row. The fields that will be merged can be decided using the '$group_into'
* argument.
*
* @param array $input The input 2-dimensional array to group.
* @param array $group_by The fields that will be used to decide if two rows
* should be merged.
* @param array $group_into The fields that will be merged for rows determined
* to be 'similar'.
* @return array The resulting grouped array.
*/
function groupArray(array $input, array $group_by, array $group_into): array {
$results = [];
$current_item = null;
$current_group = array_fill(0, count($group_by), "");
foreach ($input as $item) {
$is_item_object = is_object($item);
$item = (array) $item;
$item_group = array_map(
callback: fn($group_by_field) => $item[$group_by_field],
array: $group_by,
);
if ($item_group !== $current_group) {
if (!is_null($current_item)) {
if ($is_item_object) $results[] = (object) $current_item;
else $results[] = $current_item;
}
$current_group = $item_group;
$current_item = $item;
foreach ($group_into as $group_into_field) {
$current_item[$group_into_field] = [];
}
}
foreach ($group_into as $group_into_field) {
$current_item[$group_into_field][] = $item[$group_into_field];
}
}
if (!is_null($current_item)) {
if ($is_item_object) $results[] = (object) $current_item;
else $results[] = $current_item;
}
return $results;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment