Перемещение элементов с помощью array_chunk с PHP - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть базовый массив, в котором я использую 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"
   ]
]

(Las chunk имеет 2 элемента)

Если в последнем «чанке» есть только 2 элемента, как я могу переместить элемент первого чанка вниз, чтобы у первого элемента было 2?

Это должно выглядеть так:

[
   [
     "a",
     "b",
   ],
   [
     "c"
     "d",
     "e",
   ],
   [
     "f"
     "g",
     "h
   ]
]

(первый блок имеет 2 элемента)

Ответы [ 4 ]

0 голосов
/ 29 ноября 2018

Вы можете добавить пустые данные к вашему массиву, например, 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);
0 голосов
/ 23 ноября 2018

Самый простой способ - это многократное выполнение erray_reverse: сначала инвертировать весь массив, затем разделить, затем инвертировать каждый кусок, а затем, наконец, массив фрагментов.

Как однострочник, он выглядит какthis: $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);

next, разделите остальную часть массива: $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 элемента «остались» и даст именно то, что вы нам сказали.

Демо

0 голосов
/ 23 ноября 2018

Функционально подход множественного array_reverse вполне понятен:

$chunk = array_reverse(array_map('array_reverse', array_chunk(array_reverse($array), 3)));

Однако это довольно дорого, особенно для больших массивов.Другой способ - вырезать элементы из конца массива и добавлять их к вашему массиву:

$size = 3;
$chunk = array();
while (count($array) > 0) {
    array_unshift($chunk, array_slice($array, -$size));
    $array = array_slice($array, 0, -$size);
}

Это работает примерно в 20 раз быстрее (более 100 000 итераций) для вашего массива и примерно в 1000 раз.быстрее для массива, содержащего 600+ элементов.

0 голосов
/ 23 ноября 2018

Вы можете сначала перевернуть массив, используя 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
        )

)
...