使用PHP中的array_chunk移动元素

3

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

如果最后一个“chunk”只有2个元素,我该如何将第一个“chunk”的一个元素向下移动,以便第一个元素只有2个?

它应该看起来像这样:

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

(第一块有2个元素)

4个回答

3
最简单的方法是多次执行array_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个元素的情况,并且将产生与您所述完全相同的结果。 演示

不需要计算 $chunk_elements,因为 count($array) % 3 将会返回你所需要的。 - cmbuckley
等一下,算了。我明白你的评论了。你是正确的。 - Johannes H.
抱歉,我不会说西班牙语。 - Johannes H.
1
无论如何,@CristianMeza,请查看我在上面回复中的编辑。 - Johannes H.
感谢您的详细回复。该数组可以返回1、2或3个元素。如果我返回2,我将把第一个块的最后一个元素向下移动(线程问题),但是如果最后一个块只返回1个元素,我可以将第一个块留下1个元素,获取第二个块的第一个元素,并使第一个和第二个块都保持2个元素吗?我知道这需要花费一些时间来理解它,但结果将如下所示:http://sandbox.onlinephpfunctions.com/code/1abf11ce7243e5de7dc16e3809322943e0205f34 问候 - Cristian Bustos
显示剩余2条评论

1
你可以首先使用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
        )

)

谢谢您的帮助。我还有一个问题,如果块的最后一行只有1个元素,我该如何只取第一行的最后一个元素并将其向下移动?谢谢 - Cristian Bustos
@CristianMeza,听起来你想要在只有一个元素的块中合并这两个块?对我来说,这听起来像是一个单独的问题。 - cmbuckley
@cmbuckley 我认为他实际上想要在第一个块和最后一个块中有至少2个元素,而更喜欢最后一个块有3个元素而不是第一个。请参见我的回复,以获取解决方案。 - Johannes H.
@CristianMeza 不太确定你的意思。那听起来像是另一个问题。类似这样:https://3v4l.org/8U52a - The fourth bird
@CristianMeza 与其让我们猜测,如果您发布一个带有期望输出的不同问题,那将是获得最佳答案的最简单方式。 - cmbuckley
显示剩余2条评论

1

从功能上来说,多次使用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);
}

对于您的数组,这将比原方法(100k次迭代)快大约20倍,对于包含600个以上项的数组,速度将快1000倍。


0

你可以在数组前面添加空数据,以使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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接