如何在foreach循环中从数组中删除对象?

163

我遍历了一个对象数组,想要根据它的“id”属性删除其中一个对象,但我的代码无法正常工作。

foreach($array as $element) {
    foreach($element as $key => $value) {
        if($key == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($element);//this doesn't work
            unset($array,$element);//neither does this
        } 
    }
}

任何建议。谢谢。

2
可能是重复的问题:如何在foreach循环中删除数组元素? - 7hi4g0
6个回答

267
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

69
在使用foreach循环遍历同一数组时,删除该数组的一个元素是否安全? - Olivier Pons
27
通常情况下,这样做会导致意想不到的结果,但你可以在 PHP 的 foreach 循环中安全地使用它。点击这里阅读一个测试:http://php.net/manual/zh/control-structures.foreach.php#88578 - pangon
2
@Paritosh 我知道你很久以前发布了这个帖子,但这是因为PHP使用关联数组。所以你有一个被删除的索引:它被编码为JSON作为一个对象。这很有道理,因为关联数组就像一个“字典”。这可能会帮助到一些人。 - Ryan O'Donnell
1
你真的需要做第二个 for each 吗?难道不能只查询对象所需的“id”属性吗?为什么要检查所有其他属性。 - htafoya
4
@htafoya 不需要改变原意,您可以这样写:如果(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); } 我想当时我只是复制并修改了他的代码,向他展示如何正确地使用unset函数。 - prodigitalson
显示剩余2条评论

5

主要答案需要小心处理。

与之一起使用

[['id'=>1,'cat'=>'vip']
,['id'=>2,'cat'=>'vip']
,['id'=>3,'cat'=>'normal']

并调用该函数

foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'cat' && $value == 'vip'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

它返回结果

[2=>['id'=>3,'cat'=>'normal']

替代

[0=>['id'=>3,'cat'=>'normal']

这是因为 unset 不会重新索引数组。

如果需要,可以使用它进行重新索引。

$result=[];
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        $found=false;
        if($valueKey === 'cat' && $value === 'vip'){
            $found=true;
            $break;
        } 
        if(!$found) {
           $result[]=$element;
        }
    }
}

2
重新索引数组,您可以使用 $array = array_values($array); - piernik

2
看起来您的unset语法无效,缺乏重新索引可能会在将来造成麻烦。请参见:PHP数组部分
正确的语法如上所示。还要记住array-values进行重新索引,这样您就不会对先前删除的内容进行索引。

1
这应该可以解决问题……
reset($array);
while (list($elementKey, $element) = each($array)) {
    while (list($key, $value2) = each($element)) {
        if($key == 'id' && $value == 'searched_value') {
            unset($array[$elementKey]);
        }
    }
}

-1

您还可以在foreach值上使用引用:

foreach($array as $elementKey => &$element) {
    // $element is the same than &$array[$elementKey]
    if (isset($element['id']) and $element['id'] == 'searched_value') {
        unset($element);
    }
}

10
$element(在foreach内外使用)只是指向数组中每个元素的引用。unset($element)只会破坏引用,不会从其所属的数组中销毁引用的元素。 - Nicholas
3
$element = null不起作用,$array的长度保持不变,只是包含了null。 - Nico Westerdale

-5
我并不是一名熟练的PHP程序员,但我可以说在C#中,您无法在迭代数组时修改它。 您可能希望尝试使用foreach循环来识别要删除的元素或元素的索引,然后在循环之后删除这些元素。

15
尽管在大多数编程语言中这是不好的实践,但在PHP中,数组基本上是可以按顺序迭代的关联数组。删除较早的元素不会改变其后面元素的键。 - Ignacio Vazquez-Abrams
23
实际上,这是允许的,因为 foreach 内部使用的数组是原始数组的副本。这样,修改原始数组是完全安全的。 - Juan
70
实际上,这是允许的,因为PHP非常混乱。 - Eric G

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