使用 array_chunk 和 PHP 移动元素

Move elements using array_chunk with PHP

我有一个基本数组,我在其中使用 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 块有 2 个元素)

如果最后一个 "chunk" 只有 2 个元素,我怎样才能将第一个块的一个元素向下移动以便第一个元素有 2 个?

它应该是这样的:

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

(第一个块有 2 个元素)

您可以先使用 array_reverse, then use 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));

Demo

结果

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )

    [1] => Array
        (
            [0] => c
            [1] => d
            [2] => e
        )

    [2] => Array
        (
            [0] => f
            [1] => g
            [2] => h
        )

)

最简单的方法是多次执行 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 元素 "left over" 并且会产生您告诉我们的结果。

Demo

从功能上讲,多重 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 倍(超过 100k 次迭代),对于包含 600 多个项目的数组来说大约快 1000 倍。

您可以将空数据添加到您的数组中,以符合您的需要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);