Группировка коллекции
Группировка — это распределение элементов по «корзинам». Для каждого элемента вы выбираете ключ, и все элементы с одинаковым ключом попадают в одну корзину.
Ключ вычисляется из самого элемента. Например, первая буква слова.
В PHP нет встроенной функции groupBy. Естественный способ группировки — ассоциативный массив, ключами которого являются ключи групп, а значениями — массивы элементов. Один цикл foreach заполняет его выражением $groups[$key][] = $element. Добавление элемента по ещё не существующему ключу просто начинает новую группу — отдельный случай обрабатывать не нужно.
Ассоциативный массив PHP сохраняет порядок вставки: группы идут в том порядке, в каком появился их первый элемент, и выводимый результат одинаков при каждом запуске.
Группировка по ключу
Самая простая группировка оставляет элементы как есть и только решает, в какую корзину попадёт каждый из них.
Вычислите ключ внутри цикла и добавьте элемент в $groups[$key]. Результат сопоставляет каждому ключу массив элементов с этим ключом. Элементы внутри группы сохраняют порядок, который они имели во входных данных.
Иногда элементы нужно изменить прямо при группировке, например сохранить их в верхнем регистре. Вычислите ключ и новое значение, а затем добавьте это новое значение в группу.
Группировка слов по первой букве
$w[0] берёт первую букву слова, а strtoupper() переводит её в верхний регистр. Слова, начинающиеся с одной и той же буквы, оказываются в одном массиве. Группы идут в порядке вставки: O, затем T, затем F.
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four", "five"];
// Добавление элемента по ещё не существующему ключу начинает новую группу.
$byFirstLetter = [];
foreach ($words as $w) {
$key = strtoupper($w[0]);
$byFirstLetter[$key][] = $w;
}
echo json_encode($byFirstLetter), "\n";
Группировка с изменением значений
Ключ — первая буква в нижнем регистре. Сохраняемое значение — всё слово в верхнем регистре. Цикл вычисляет и то и другое и добавляет значение в $groups[$key].
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four", "five"];
$groups = [];
foreach ($words as $w) {
$key = $w[0]; // первая буква в нижнем регистре
$value = strtoupper($w); // значение, сохраняемое в группе
$groups[$key][] = $value;
}
echo json_encode($groups), "\n";
Подсчёт элементов каждой группы
Часто элементы каждой группы не нужны — важно только их количество.
В PHP есть встроенный счётчик: array_count_values(). Он подсчитывает, как часто каждое значение встречается в массиве. Чтобы подсчитать слова по первой букве, сначала превратите каждое слово в его первую букву с помощью array_map(), а затем позвольте array_count_values() подсчитать буквы.
Подсчёт слов по первой букве
array_map() превращает слова в буквы o, t, t, f, f. Затем array_count_values() подсчитывает каждую букву: одна o, две t, две f.
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four", "five"];
// array_count_values() подсчитывает, как часто встречается каждое значение.
$letters = array_map(fn($w) => $w[0], $words);
$counts = array_count_values($letters);
echo json_encode($counts), "\n";
Свёртка и редукция по группам
Свёртка группы — это пошаговое объединение её элементов в одно значение. Классический пример — текущая сумма: начните с 0 и прибавляйте каждый элемент.
Способ PHP — ассоциативный массив, который хранит текущее значение каждой группы. Для каждого элемента вычислите его ключ и обновите значение, сохранённое под этим ключом.
Чтение ещё отсутствующего в массиве ключа вызвало бы предупреждение, поэтому используйте оператор ??: $sums[$key] ?? 0 без лишнего шума даёт 0, когда ключа нет. Если значение должно начинаться с самого первого элемента, проверяйте наличие ключа с помощью isset().
Сумма каждой группы
Каждое число попадает в группу "even" или "odd" и прибавляется к сумме этой группы. ($sums[$key] ?? 0) + $n начинает новую группу с 0, поэтому отдельный случай не нужен.
Вывод: PHP-скрипт
<?php
$numbers = [3, 4, 5, 6, 7, 8];
// С оператором ?? отсутствующий ключ даёт 0, поэтому сложение не требует особого случая.
$sums = [];
foreach ($numbers as $n) {
$key = $n % 2 === 0 ? "even" : "odd";
$sums[$key] = ($sums[$key] ?? 0) + $n;
}
echo json_encode($sums), "\n";
Построение строки для каждой группы
Первое число группы начинает строку. Каждое следующее число присоединяется через "+". isset($chains[$key]) различает эти два случая, а (string)$n превращает первое число в текст.
Вывод: PHP-скрипт
<?php
$numbers = [3, 4, 5, 6, 7, 8];
$chains = [];
foreach ($numbers as $n) {
$key = $n % 2 === 0 ? "even" : "odd";
// Первое число группы начинает строку; следующие присоединяются через "+".
if (!isset($chains[$key])) {
$chains[$key] = (string)$n;
} else {
$chains[$key] .= "+" . $n;
}
}
echo json_encode($chains), "\n";