Как удалить объект из массива внутри цикла foreach?


142

Я перебираю массив объектов и хочу удалить один из объектов на основе его свойства 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
        } 
    }
}

Какие-либо предложения. Спасибо.


Ответы:


237
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]);
        } 
    }
}

63
Безопасно ли удалять элемент массива в цикле foreach того же массива?
Оливье Понс,

25
@Oliver: обычно это вызывает неожиданное поведение, но вы можете сделать это безопасно с помощью foreach на php. Прочтите здесь для теста: php.net/manual/en/control-structures.foreach.php#88578
pangon

1
@Paritosh Я знаю, что вы опубликовали это очень давно, но это потому, что PHP использует ассоциативные массивы. Итак, у вас есть удаленный индекс, и он кодируется в JSON как объект. Имеет смысл, поскольку ассоциативный массив - это «словарь». Могу помочь кому-нибудь, кто придет.
Райан О'Доннелл,

1
Вам действительно нужно делать второе для каждого? не могли бы вы просто запросить желаемое свойство id объекта? Зачем проверять все остальные реквизиты.
htafoya 06

3
@htafoya нет, ты мог бы просто, if(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); }я думаю, в то время я просто скопировал и изменил его код, чтобы показать ему, как unsetправильно.
prodigitalson

2

Похоже, ваш синтаксис для unset неверен, и отсутствие переиндексации может вызвать проблемы в будущем. См .: раздел о массивах PHP .

Правильный синтаксис показан выше. Также помните о значениях массивов для переиндексации, чтобы никогда не индексировать то, что вы ранее удалили.


2

Вы также можете использовать ссылки на foreachзначения:

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

9
$ element (используется как в foreach, так и вне его) - это просто ссылка на каждый элемент в массиве. unset ($ element) просто разорвет ссылку, он не уничтожит указанный элемент из своего массива.
Николас

3
@Dev_NIX $element = nullНЕ будет работать, длина $arrayостанется прежней, он будет содержать только нули
Нико

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

Будьте осторожны с основным ответом.

с участием

[['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;
        }
    }
}

0

Я не особо разбираюсь в php-программировании, но могу сказать, что в C # вы не можете изменять массив во время итерации по нему. Вы можете попробовать использовать цикл foreach для определения индекса элемента или элементов, которые нужно удалить, а затем удалить элементы после цикла.


14
Хотя это плохая практика для большинства языков, массивы в PHP в основном представляют собой ассоциативные массивы, которые можно повторять по порядку. Удаление более раннего элемента не меняет ключи элементов, следующих за ним.
Игнасио Васкес-Абрамс,

22
На самом деле это разрешено, потому что массив, который используется внутри foreach, является копией исходного массива. Таким образом, изменение исходного массива совершенно безопасно.
Хуан,

69
На самом деле, это разрешено, потому что php чертовски крут.
Eric G
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.