如何移除数组元素并重新索引数组?

237

我有一个数组的问题。我想要修改这个数组如下。我希望通过索引来移除数组中的某些元素,然后重新对数组进行索引。是否可能?

$foo = array(

    'whatever', // [0]
    'foo', // [1]
    'bar' // [2]

);

$foo2 = array(

    'foo', // [0], before [1]
    'bar' // [1], before [2]

);
8个回答

526
unset($foo[0]); // remove item at index 0
$foo2 = array_values($foo); // 'reindex' array

4
如果需要一次性删除多个项目,并且这些项目的索引已经被收集好了,那么这种解决方案比deceze的方案更好。因为使用array_splice函数删除第一个项目后,剩下项目的索引就会丢失。请注意,不改变原意。 - Jānis Elmeris
28
值得注意的是,您可以通过单个unset调用来取消设置多个变量/数组索引,例如unset($foo[0], $foo[3], $bar[1]); - ᴍᴀᴛᴛ ʙᴀᴋᴇʀ

51

5
谨慎在循环中使用此方法,因为它会使循环的数组索引和实际数组的索引不同步。 - Mouagip

29

你最好使用 array_shift()。它会返回数组的第一个元素,将其从数组中移除并重新索引数组。这是一种高效的方法。


4
如果你想要检索并删除数组的第一个元素,并在此过程中重新索引数组,那么这很好。如果你需要检索并删除最后一个数组元素,则其对应的函数array_pop()将实现此功能。但是,这两个函数都不能针对数组中间的元素执行操作。 - Derrick Miller
2
虽然这与正交有关,但问题明确是关于数组中的任何元素,而不仅仅是第一个元素。 - Félix Adriyel Gagnon-Grenier

13
array_splice($array, array_search(array_value, $array), 1);

数组值将为'whatever'。 - user1092222
解释应该放在问题中,而不是作为评论发布在问题下面。 - mickmackusa

11

2020 PHP 7.4性能基准测试

对于那些对当前答案不满意的人,我写了一个小的基准测试脚本,任何人都可以从CLI运行。

我们将比较两种解决方案:

使用array_values()和unset()使用array_splice()

<?php

echo 'php v' . phpversion() . "\n";

$itemsOne = [];
$itemsTwo = [];

// populate items array with 100k random strings
for ($i = 0; $i < 100000; $i++) {
    $itemsOne[] = $itemsTwo[] = sha1(uniqid(true));
}

$start = microtime(true);

for ($i = 0; $i < 10000; $i++) {
    unset($itemsOne[$i]);
    $itemsOne = array_values($itemsOne);
}

$end = microtime(true);

echo 'unset & array_values: ' . ($end - $start) . 's' . "\n";

$start = microtime(true);

for ($i = 0; $i < 10000; $i++) {
    array_splice($itemsTwo, $i, 1);
}

$end = microtime(true);

echo 'array_splice: ' . ($end - $start) . 's' . "\n"; 

正如您所看到的,这个思路很简单:

  • 创建两个数组,都有相同的100k个项目(随机生成的字符串)
  • 使用unset()和array_values()从第一个数组中删除前10k个项目以重新索引
  • 使用array_splice()从第二个数组中删除前10k个项目
  • 测量两种方法的时间

在我的Dell Latitude i7-6600U 2.60GHz x 4和15.5GiB RAM上运行上述脚本的输出:

php v7.4.8
unset & array_values: 29.089932918549s
array_splice: 17.94264793396s

结论:array_splice 的性能几乎是 unset 和 array_values 的两倍。

因此:array_splice 胜出!


2
第三个测试是使用unset()取消所有10k,然后运行array_values()一次重新索引,而不是在每个循环中重新索引。对我来说,这比使用你的脚本中的array_splice()快约5%。 - shinypenguin

9
Unset($array[0]); 

Sort($array); 

我不知道为什么这个被踩了,但如果有人尝试过,你会注意到它是有效的。 在数组上使用sort会重新分配数组的键。唯一的缺点是它对值进行排序。 由于键显然将被重新分配,即使使用array_values,值是否被排序都无关紧要。


11
即使钥匙将被重新分配,在正确答案中,初始顺序仍将被保留。 - s3v3n
2
“我想通过索引删除它的元素(们),然后重新索引数组。这可行吗?”@s3v3n,原帖并没有要求保持初始顺序。我只是提供了一个能够实现所述功能的解决方案。 - frostymarvelous
@s3v3n,这并不是怨恨。我只是想知道为什么。显然是为了在以后的答案中有所提高。我同意有更好的方法,但这个回答为什么如此糟糕?是性能问题吗?等等?我来到SO也是为了学习和教授。 - frostymarvelous
通常情况下,程序员极有可能需要以与输入相同的顺序获取这些值。例如,从数据库中选取一些行应该以表格形式显示,或者在聊天应用程序中回复应该以完全相同的顺序出现。例子可以无限多,重点是在大多数情况下,顺序需要保持相同,或者至少程序员期望数组中元素的顺序相同。 - s3v3n
好的。数据库的示例对我来说非常清晰易懂。感谢您抽出时间。 - frostymarvelous
这个答案是误导性的。这就是为什么它正在收集反对票的原因。它正在做一些问题中没有要求的事情。提问者不想重新排序值,他们只想重新索引数组。这个答案是不正确/不合适的。 - mickmackusa

5

尝试以下操作:

$foo2 = array_slice($foo, 1);

这仅适用于第一个元素,而不是任意一个。 - Felix Kling

0

过一段时间后,我将把所有数组元素(不包括这些不需要的元素)复制到新数组中


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