有没有一种简单的方法可以使用PHP从数组中删除元素,从而foreach($array)不再包含该元素?

我以为将其设置为null就可以了,但显然它不起作用。


当前回答

关联阵列

对于关联阵列,请使用unset:

$arr = array('a' => 1, 'b' => 2, 'c' => 3);
unset($arr['b']);

// RESULT: array('a' => 1, 'c' => 3)

数值数组

对于数值数组,请使用array_spling:

$arr = array(1, 2, 3);
array_splice($arr, 1, 1);

// RESULT: array(0 => 1, 1 => 3)

Note

对数值数组使用unset不会产生错误,但会打乱索引:

$arr = array(1, 2, 3);
unset($arr[1]);

// RESULT: array(0 => 1, 2 => 3)

其他回答

需要注意的是,unset()将保持索引不变,这是使用字符串索引(数组作为哈希表)时所期望的,但在处理整数索引数组时可能会非常令人惊讶:

$array = array(0, 1, 2, 3);
unset($array[2]);
var_dump($array);
/* array(3) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [3]=>
  int(3)
} */

$array = array(0, 1, 2, 3);
array_splice($array, 2, 1);
var_dump($array);
/* array(3) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(3)
} */

因此,如果您想规范化整数键,可以使用array_splice()。另一个选项是在unset()之后使用array_values():

$array = array(0, 1, 2, 3);

unset($array[2]);
$array = array_values($array);
var_dump($array);
/* array(3) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(3)
} */
<?php
    $stack = ["fruit1", "fruit2", "fruit3", "fruit4"];
    $fruit = array_shift($stack);
    print_r($stack);

    echo $fruit;
?>

输出:

[
    [0] => fruit2
    [1] => fruit3
    [2] => fruit4
]

fruit1

我来这里是因为我想看看是否有比使用unset($arr[$I])更优雅的解决方案来解决这个问题。令我失望的是,这些答案要么是错误的,要么没有涵盖所有边缘情况。

这就是array_diff()不起作用的原因。键在数组中是唯一的,而元素并不总是唯一的。

$arr = [1,2,2,3];

foreach($arr as $i => $n){
    $b = array_diff($arr,[$n]);
    echo "\n".json_encode($b);
}

后果

[2,2,3]
[1,3]
[1,2,2] 

如果两个元素相同,则将删除它们。这也适用于array_search()和array_flip()。

我看到了很多关于array_slice()和array_splice()的答案,但这些函数只适用于数值数组。如果这里没有回答这个问题,我知道所有的答案,所以这里有一个可行的解决方案。

$arr = [1,2,3];

foreach($arr as $i => $n){
    $b = array_merge(array_slice($arr,0,$i),array_slice($arr,$i+1));
    echo "\n".json_encode($b);
}

Results...

[2,3];
[1,3];
[1,2];

由于unset($arr[$i])将同时适用于关联数组和数值数组,所以这仍然不能回答这个问题。

这个解决方案是比较键和,使用一个同时处理数字和关联数组的工具。为此,我使用了array_diff_uassoc()。此函数用于比较回调函数中的按键。

$arr = [1,2,2,3];
//$arr = ['a'=>'z','b'=>'y','c'=>'x','d'=>'w'];
foreach($arr as $key => $n){
    $b = array_diff_uassoc($arr, [$key=>$n], function($a,$b) {
        if($a != $b){
            return 1;
        }
    });
    echo "\n".json_encode($b);
}    

后果

[2,2,3];
[1,2,3];
[1,2,2];

['b'=>'y','c'=>'x','d'=>'w'];
['a'=>'z','c'=>'x','d'=>'w'];
['a'=>'z','b'=>'y','d'=>'w'];
['a'=>'z','b'=>'y','c'=>'x'];

unset()数组中的多个碎片元素

虽然这里多次提到unset(),但还需要提到的是,unset(()接受多个变量,从而可以在一次操作中轻松删除数组中的多个非连续元素:

// Delete multiple, noncontiguous elements from an array
$array = [ 'foo', 'bar', 'baz', 'quz' ];
unset( $array[2], $array[3] );
print_r($array);
// Output: [ 'foo', 'bar' ]

动态取消设置()

unset()不接受要删除的键数组,因此下面的代码将失败(但这会使动态使用unset(()稍微容易一些)。

$array = range(0,5);
$remove = [1,2];
$array = unset( $remove ); // FAILS: "unexpected 'unset'"
print_r($array);

相反,unset()可以在foreach循环中动态使用:

$array = range(0,5);
$remove = [1,2];
foreach ($remove as $k=>$v) {
    unset($array[$v]);
}
print_r($array);
// Output: [ 0, 3, 4, 5 ]

通过复制数组来删除数组键

还有一种做法尚待提及。有时,消除某些数组键的最简单方法是将$array1复制到$array2中。

$array1 = range(1,10);
foreach ($array1 as $v) {
    // Remove all even integers from the array
    if( $v % 2 ) {
        $array2[] = $v;
    }
}
print_r($array2);
// Output: [ 1, 3, 5, 7, 9 ];

显然,同样的做法适用于文本字符串:

$array1 = [ 'foo', '_bar', 'baz' ];
foreach ($array1 as $v) {
    // Remove all strings beginning with underscore
    if( strpos($v,'_')===false ) {
        $array2[] = $v;
    }
}
print_r($array2);
// Output: [ 'foo', 'baz' ]

使用以下代码:

$arr = array('orange', 'banana', 'apple', 'raspberry');
$result = array_pop($arr);
print_r($result);