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

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

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


person ababa    schedule 21.02.2010    source источник
comment
возможный дубликат Как удалить элемент массива в цикле foreach?   -  person 7hi4g0    schedule 29.01.2014


Ответы (6)


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

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

person pablo.meier    schedule 21.02.2010

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

foreach($array as $elementKey => &$element) {
    // $element is the same than &$array[$elementKey]
    if (isset($element['id']) and $element['id'] == 'searched_value') {
        unset($element);
    }
}
person air-dex    schedule 09.06.2015
comment
$ element (используется в foreach и вне его) - это просто ссылка на каждый элемент в массиве. unset ($ element) просто разорвет ссылку, она не уничтожит указанный элемент из своего массива. - person Nicholas; 20.01.2016
comment
@Dev_NIX $element = null НЕ будет работать, длина $array останется прежней, он будет содержать только нули - person Nico Westerdale; 06.09.2017

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

с участием

[['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;
        }
    }
}
person magallanes    schedule 18.04.2020
comment
Чтобы переиндексировать массив, вы можете использовать $array = array_values($array); - person piernik; 14.05.2021

Это должно помочь ...

reset($array);
while (list($elementKey, $element) = each($array)) {
    while (list($key, $value2) = each($element)) {
        if($key == 'id' && $value == 'searched_value') {
            unset($array[$elementKey]);
        }
    }
}
person Josh    schedule 07.02.2013

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

person Corey Sunwold    schedule 21.02.2010
comment
Хотя это плохая практика для большинства языков, массивы в PHP в основном представляют собой ассоциативные массивы, которые можно повторять по порядку. Удаление более раннего элемента не меняет ключи элементов, следующих за ним. - person Ignacio Vazquez-Abrams; 21.02.2010
comment
На самом деле это разрешено, потому что массив, который используется внутри foreach, является копией исходного массива. Таким образом, изменение исходного массива совершенно безопасно. - person Juan; 21.02.2010
comment
На самом деле это разрешено, потому что php чертовски хреновый. - person Eric G; 07.04.2013

person    schedule
comment
Безопасно ли удалять элемент массива в цикле foreach того же массива? - person Olivier Pons; 06.08.2012
comment
@Oliver: обычно это вызывает неожиданное поведение, но вы можете сделать это безопасно с помощью foreach на php. Прочтите здесь для теста: php.net/manual/en/ control-structure.foreach.php # 88578 - person pangon; 26.01.2013
comment
Это преобразовывает мой массив в объект в CodeIgniter. Любое предложение? - person Paritosh; 06.10.2016
comment
@Paritosh Я знаю, что вы опубликовали это давным-давно, но это потому, что PHP использует ассоциативные массивы. Итак, у вас есть удаленный индекс: он кодируется в JSON как объект. Имеет смысл, поскольку ассоциативный массив - это словарь. Может помочь кому-нибудь, кто придет. - person Ryan O'Donnell; 27.02.2017
comment
Вам действительно нужно делать второе для каждого? не можете ли вы просто запросить желаемое свойство id объекта? Зачем проверять все остальные реквизиты. - person htafoya; 07.12.2017
comment
@htafoya нет, ты мог бы просто сделать if(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); } Я думаю, что в то время я просто скопировал и изменил его код, чтобы показать ему, как правильно unset. - person prodigitalson; 22.12.2017
comment
Ответ @pangon может ввести в заблуждение. Его ссылка показывает, что foreach цикл не зависит от unset. Безопасно это или нет, зависит от конкретного варианта использования. - person Binod Kalathil; 04.07.2020