У меня есть базовый массив, в котором я использую array_chunk, чтобы разделить его на 3 элемента.
$array = array(
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'
);
$chunk = array_chunk($array, 3);
Результат выглядит следующим образом
[
[
"a",
"b",
"c"],
[
"d",
"e",
"f"],
[
"g",
"h"]
]
(Лас чанк имеет 2 элемента)
Если последний «чанк» имеет только 2 элемента, как я могу переместить элемент первого чанка вниз, чтобы у первого элемента было 2?
Это должно выглядеть так:
[
[
"a",
"b",
],
[
"c""d",
"e",
],
[
"f""g",
"h
]
]
(Первый кусок имеет 2 элемента)
Самым простым способом является многократное выполнение erray_reverse: сначала инвертировать весь массив, затем разделить, затем инвертировать каждый фрагмент, а затем, наконец, массив фрагментов.
Как однострочник, это выглядит так: $chunk = array_reverse(array_map('array_reverse', array_chunk(array_reverse($array), 3)));
Имейте в виду, однако, что обращение к массиву является дорогостоящей операцией, поэтому, если ваш массив является более точным, чем в вашем примере, это не рекомендуется.
Более эффективный, но также и больше кода:
Рассчитать количество элементов, которые должны быть в первом чанке, по модулю:
$first_chunk_size = count($array) % 3;
Далее, чтобы избежать пустого массива, если размер массива кратен размеру куска, исправьте размер куска, если по модулю выдает 0:
$first_chunk_size = $first_chunk_size == 0 ? 3 : $first_chunk_size;
затем отрезаем первую часть:
$first_chunk = array_slice($array, 0, $first_chunk_size);
Затем разделите остальную часть массива:
$chunks = array_chunk(array_slice($array,$first_chunk_size),3);
затем объедините первый блок и другие блоки в один массив:
array_unshift($chunks, $first_chunk);
Полный код второго подхода:
$array = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'
];
$first_chunk_size = count($array) % 3;
$first_chunk_size = $first_chunk_size == 0 ? 3 : $first_chunk_size;
$first_chunk = array_slice($array, 0, $first_chunk_size);
$chunks = array_chunk(array_slice($array,$first_chunk_size),3);
array_unshift($chunks, $first_chunk);
var_dump($chunks);
(очевидно, этот код можно упростить, если не делать все шаг за шагом)
РЕДАКТИРОВАТЬ: Прочитав ваши комментарии к другим ответам, вы можете немного изменить этот подход и превратить его в функцию повторного получения. С некоторой очисткой кода. это может выглядеть так:
$array = [
'a', 'b', 'c', 'd', 'e', 'f', 'g'
];
function custom_array_chunk ($array) {
$first_chunk_size = count($array) % 3;
if ($first_chunk_size == 0) {
$chunks = array_chunk($array, 3);
} else {
$chunks = custom_array_chunk(array_slice($array,2));
array_unshift($chunks, array_slice($array, 0, 2));
}
return $chunks;
}
var_dump(custom_array_chunk($array));
Это будет работать для обоих случаев, 1 и 2 элемента «осталось» и даст именно то, что вы сказали нам.
Вы можете сначала перевернуть массив, используя array_reverse, затем используйте array_chunk. Затем переверните внутренние массивы и снова переверните внешние массивы:
$array = array(
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h'
);
$array = array_reverse($array);
$chunk = array_chunk($array, 3);
$array = array_map('array_reverse', $chunk);
print_r(array_reverse($array));
Результат
Array
(
[0] => Array
(
[0] => a
[1] => b
)
[1] => Array
(
[0] => c
[1] => d
[2] => e
)
[2] => Array
(
[0] => f
[1] => g
[2] => h
)
)
Функционально подход множественного array_reverse вполне понятен:
$chunk = array_reverse(array_map('array_reverse', array_chunk(array_reverse($array), 3)));
Тем не менее, это довольно дорого, особенно для больших массивов. Другой способ — вырезать элементы из конца массива и добавить их к массиву chunked:
$size = 3;
$chunk = array();
while (count($array) > 0) {
array_unshift($chunk, array_slice($array, -$size));
$array = array_slice($array, 0, -$size);
}
Это работает примерно в 20 раз быстрее (более 100 тыс. Итераций) для вашего массива и примерно в 1000 раз быстрее для массива, содержащего более 600 элементов.
Вы можете добавить пустые данные к вашему массиву, в виде array_chunk, который будет соответствовать вашим потребностям.
Затем удалите эти предварительно подготовленные данные.
$chunk = 3;
$nbToPrepend = ($chunk - count($array) % $chunk);
$prepend = array_fill(0, $nbToPrepend, null);
$result = array_chunk(array_merge($prepend, $array), $chunk);
$result[0] = array_slice($result[0], $nbToPrepend);