Как удалить объект из массива внутри цикла 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.