Разделение массивов на сегменты средствами PHP

Раздел: PHP -> Массивы

Разбиение массива на части в PHP

Основное решение: функция array_chunk

Как разделить массив на равные части заданного размера?

Стандартная функция array_chunk принимает массив и количество элементов в каждой части, а возвращает многомерный массив. Пример:

$array = [1, 2, 3, 4, 5, 6, 7];
$chunks = array_chunk($array, 3);
print_r($chunks);
Array
(
    [0] => Array ( [0] => 1 [1] => 2 [2] => 3 )
    [1] => Array ( [0] => 4 [1] => 5 [2] => 6 )
    [2] => Array ( [0] => 7 )
)

Последняя часть может содержать меньше элементов, если исходный массив не делится нацело. Функция не изменяет исходный массив.

Возможные трудности:

  • При передаче отрицательного или нулевого размера части возникает ошибка (E_WARNING). Требуется проверять входящее значение.
  • Для ассоциативных массивов ключи сбрасываются на числовые, если не использовать третий аргумент true.
  • Функция не умеет создавать части по произвольному условию, только по фиксированному размеру.

Вариант 1: Сохранение строковых ключей

Как разбить ассоциативный массив, не теряя ключи элементов?

Третий параметр preserve_keys в array_chunk решает эту задачу. Пример:

$assoc = ['a' => 'Apple', 'b' => 'Banana', 'c' => 'Cherry', 'd' => 'Date'];
$chunks = array_chunk($assoc, 2, true);
print_r($chunks);
Array
(
    [0] => Array ( [a] => Apple [b] => Banana )
    [1] => Array ( [c] => Cherry [d] => Date )
)

Ключи каждого элемента сохраняются внутри соответствующей части.

Особенности:

  • При true функция не переиндексирует элементы, что сохраняет исходную структуру.
  • Если массив был числовым, но с пропусками в индексах, ключи также остаются прежними.

Вариант 2: Разбиение с помощью array_slice в цикле

Как реализовать разбиение без встроенной функции, с полным контролем процесса?

Используется цикл for или while, на каждом шаге извлекается часть через array_slice. Пример:

$array = [10, 20, 30, 40, 50, 60];
$size = 4;
$result = [];
for ($i = 0; $i < count($array); $i += $size) {
    $result[] = array_slice($array, $i, $size);
}
print_r($result);
Array
(
    [0] => Array ( [0] => 10 [1] => 20 [2] => 30 [3] => 40 )
    [1] => Array ( [4] => 50 [5] => 60 )
)

Обратите внимание: array_slice по умолчанию сбрасывает ключи, если третий параметр не указан как true.

Типичные ошибки:

  • Неправильное смещение $i при изменении массива во время цикла – в данном случае массив не меняется, поэтому ошибка маловероятна.
  • Забыть про array_slice с сохранением ключей, если они важны.
  • Бесконечный цикл из-за неверного условия выхода – рекомендуется кешировать длину массива до цикла.

Вариант 3: Разбиение через array_splice

Как извлечь часть массива, удаляя её из исходного?

array_splice удаляет выбранные элементы из исходного массива и возвращает их. Если нужно последовательно разбирать массив на части, этот способ изменяет оригинал. Пример:

$array = [1, 2, 3, 4, 5, 6];
$size = 2;
$parts = [];
while (count($array) > 0) {
    $parts[] = array_splice($array, 0, $size);
}
print_r($parts);
Array
(
    [0] => Array ( [0] => 1 [1] => 2 )
    [1] => Array ( [0] => 3 [1] => 4 )
    [2] => Array ( [0] => 5 [1] => 6 )
)

Исходный массив после цикла станет пустым.

Предостережения:

  • Модификация исходного массива может быть нежелательной. Стоит создавать копию, если оригинал требуется позже.
  • При работе с ассоциативными массивами нужно учитывать, что array_splice переиндексирует числовые ключи, но строковые ключи могут вести себя непредсказуемо.

Вариант 4: Разбиение с помощью array_chunk и дальнейшая обработка

Как разбить массив на части, а затем выполнить преобразование каждой части?

Комбинация array_chunk и array_map позволяет применить функцию к каждому блоку. Пример:

$data = [2, 4, 6, 8, 10];
$chunks = array_chunk($data, 2);
$sums = array_map('array_sum', $chunks);
print_r($sums);
Array
(
    [0] => 6
    [1] => 18
    [2] => 10
)

Таким образом можно вычислять сумму, среднее или выполнять любую обработку каждой группы.

Недостатки:

  • Для больших массивов может потребоваться много памяти при одновременном хранении частей.
  • При нерегулярном размере частей последняя группа может быть меньше.

Цели применения разных вариантов:

  • array_chunk – простейший и самый быстрый способ для однородных числовых массивов.
  • array_chunk с preserve_keys – для ассоциативных массивов, где важна оригинальная привязка ключей.
  • Ручной цикл с array_slice – когда нужен дополнительный контроль или сложная логика разбиения.
  • array_splice – если требуется модифицировать исходный массив (использовать как очередь).
  • Комбинация с array_map – для обработки каждого фрагмента без явного цикла.

Расширенные примеры разбиения массивов

1. Разбиение ассоциативного массива с сохранением ключей

Пример
$users = [
    'user1' => ['name' => 'Alice', 'age' => 30],
    'user2' => ['name' => 'Bob', 'age' => 25],
    'user3' => ['name' => 'Charlie', 'age' => 35],
    'user4' => ['name' => 'Diana', 'age' => 28]
];
$chunks = array_chunk($users, 2, true);
print_r($chunks);
Array
(
    [0] => Array
        (
            [user1] => Array ( [name] => Alice [age] => 30 )
            [user2] => Array ( [name] => Bob [age] => 25 )
        )
    [1] => Array
        (
            [user3] => Array ( [name] => Charlie [age] => 35 )
            [user4] => Array ( [name] => Diana [age] => 28 )
        )
)

2. Разбиение на разные размеры частей (неравномерное)

Иногда требуется разбить массив на части, где каждая следующая часть имеет разный размер. Например, первая часть 3 элемента, вторая 2, третья 4. Реализуется вручную:

Пример
$items = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
$sizes = [3, 2, 4];
$result = [];
$offset = 0;
foreach ($sizes as $size) {
    $result[] = array_slice($items, $offset, $size);
    $offset += $size;
}
print_r($result);
Array
(
    [0] => Array ( [0] => A [1] => B [2] => C )
    [1] => Array ( [0] => D [1] => E )
    [2] => Array ( [0] => F [1] => G [2] => H [3] => I )
)

3. Разбиение с группировкой по условию

Пусть есть массив чисел, и требуется разбить его на части, каждая из которых состоит из последовательных чисел, разность между которыми не превышает 2:

Пример
$numbers = [1, 2, 3, 10, 11, 12, 20, 21];
$chunks = [];
$group = [];
$prev = null;
foreach ($numbers as $num) {
    if ($prev === null || ($num - $prev) <= 2) {
        $group[] = $num;
    } else {
        $chunks[] = $group;
        $group = [$num];
    }
    $prev = $num;
}
if (!empty($group)) {
    $chunks[] = $group;
}
print_r($chunks);
Array
(
    [0] => Array ( [0] => 1 [1] => 2 [2] => 3 )
    [1] => Array ( [0] => 10 [1] => 11 [2] => 12 )
    [2] => Array ( [0] => 20 [1] => 21 )
)

4. Пагинация: разбиение на страницы с ключом-номером страницы

Пример
$allItems = range(1, 25);
$perPage = 6;
$pages = array_chunk($allItems, $perPage);
$pagesWithOffset = [];
foreach ($pages as $index => $chunk) {
    $pagesWithOffset['page_' . ($index + 1)] = $chunk;
}
print_r($pagesWithOffset);
Array
(
    [page_1] => Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 )
    [page_2] => Array ( [0] => 7 [1] => 8 [2] => 9 [3] => 10 [4] => 11 [5] => 12 )
    [page_3] => Array ( [0] => 13 [1] => 14 [2] => 15 [3] => 16 [4] => 17 [5] => 18 )
    [page_4] => Array ( [0] => 19 [1] => 20 [2] => 21 [3] => 22 [4] => 23 [5] => 24 )
    [page_5] => Array ( [0] => 25 )
)

5. Разбиение с помощью генератора (экономия памяти)

Пример
function chunkGenerator($array, $size) {
    for ($i = 0; $i < count($array); $i += $size) {
        yield array_slice($array, $i, $size);
    }
}
$bigArray = range(1, 100000);
$chunks = chunkGenerator($bigArray, 100);
foreach ($chunks as $index => $chunk) {
    if ($index >= 3) break; // обрабатываем только первые 3 части
    echo 'Part ' . ($index + 1) . ': ' . count($chunk) . ' elements
'; }
Part 1: 100 elements
Part 2: 100 elements
Part 3: 100 elements

6. Разбиение с восстановлением исходного массива

Если после разбиения нужно вернуть исходный порядок, можно использовать array_merge с распаковкой:

Пример
$original = [5, 10, 15, 20];
$chunks = array_chunk($original, 2);
$restored = array_merge(...$chunks);
print_r($restored);
Array
(
    [0] => 5
    [1] => 10
    [2] => 15
    [3] => 20
)

Разбиение массива на части в PHP - comments

En
Php разбить массив (php)