Як видалити об'єкт з масиву всередині циклу foreach?


140

Я повторюю масив об'єктів і хочу видалити один із об'єктів, заснований на властивості '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
        } 
    }
}

Будь-які пропозиції. Дякую.


Відповіді:


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

62
Чи безпечно видаляти елемент масиву в циклі foreach того ж масиву?
Олів'є Понс

25
@Oliver: зазвичай це призведе до несподіваної поведінки, але ви можете це зробити безпечно, використовуючи foreach на php. Ознайомтесь з тестом: php.net/manual/en/control-structures.foreach.php#88578
pangon

1
@Paritosh Я знаю, що ви розміщували це давно, але це тому, що PHP використовує асоціативні масиви. Отже, у вас видалений індекс: він кодується до JSON як Об'єкт. Має сенс, оскільки асоціативний масив - це «словник». Може допомогти тому, хто йде разом.
Райан О'Доннелл

1
Вам справді потрібно робити другу для кожного? Ви не можете просто запитати потрібне властивість 'id' об'єкта? Навіщо перевіряти всі інші реквізити.
хтафоя

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

2

Схоже, ваш синтаксис для скасування недійсний, і відсутність повторного детексування може спричинити проблеми в майбутньому. Дивіться: розділ про масиви 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
$ елемент (використовується в і поза foreach) - це лише посилання на кожен елемент масиву. unset ($ елемент) просто порушить посилання, він не знищить посилається елемент зі свого масиву.
Микола

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 використовує внутрішньо, - це копія вихідного масиву. Таким чином, модифікація вихідного масиву є абсолютно безпечною.
Хуан

68
Насправді, це дозволено, тому що php є гнучким, як усе пекло.
Ерік Г
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.