I have a simple array with some names in it and I want to group them by their first letter. E.g. all names with A to C as first letter go in an array and D to F go to another on
This is a good use of array_reduce in a non-scalar fashion:
function keyize(string $word, $stride = 3): string {
$first = strtoupper($word{0});
$index = (int)floor((ord($first) - ord('A'))/$stride);
return implode('', array_chunk(range('A', 'Z'), $stride)[$index]);
}
function bucketize(array $words, $stride = 3): array {
return array_reduce(
$words,
function ($index, $word) use ($stride) {
$index[keyize($word, $stride)][] = $word;
return $index;
},
[]
);
}
$words = [ 'alpha', 'Apple', 'Bravo', 'banana', 'charlie', 'Cucumber', 'echo', 'Egg', ];
shuffle($words);
$buckets = bucketize($words, 3); // change the number of characters you want grouped, eg 1, 13, 26
ksort($buckets);
var_dump($buckets);
So we're using array_reduce to walk - and simultaneously build - the buckets. It's not the most efficient as implemented, because the bucket array is copied through each closure invocation. However, it's compact.