Як видалити елемент масиву в циклі foreach?


127

Я хочу провести цикл через масив, foreachщоб перевірити, чи існує значення. Якщо значення існує, я хочу видалити елемент, який його містить.

У мене є такий код:

foreach($display_related_tags as $tag_name) {
    if($tag_name == $found_tag['name']) {
        // Delete element
    }
}

Я не знаю, як видалити елемент, як тільки знайдено значення. Як її видалити?

Мені доводиться використовувати foreachдля цієї проблеми. Ймовірно, є альтернативи foreach, і ви можете їм поділитися.

Відповіді:


220

Якщо ви також отримаєте ключ, ви можете видалити цей елемент так:

foreach ($display_related_tags as $key => $tag_name) {
    if($tag_name == $found_tag['name']) {
        unset($display_related_tags[$key]);
    }
}

3
Деякі додаткові відомості про оптимізацію за допомогою $key => &$tag_name stackoverflow.com/a/2008893/922522
Джастін

5
Зауважте, що індексовані масиви з вимкненими елементами можуть бути представлені у вигляді об'єктів замість масивів після а json_encode(). Ви можете вирішити це $display_related_tags = array_values ($display_related_tags);за допомогою foreachциклу.
Márton Tamás

Зауважте, у цьому полягає хитрість - додати значення циклу foreach ;-)
Містер Вашингтон

5
Дивіться відповідь @Neils. У вас виникнуть несподівані помилки, особливо якщо ви працюєте з масивом stdClasses. Вам подобається несподівана поведінка? Я ні.
happy_marmoset

@happy_marmoset Нілс відповідь не допомагає. Знімок, який $projects = array_filter($projects, function ($project) { return count($project->roles) > 0; });він перетворює, призводить до об'єкта.
Парітош

36

Кращим рішенням є використання array_filterфункції:

$display_related_tags =
    array_filter($display_related_tags, function($e) use($found_tag){
        return $e != $found_tag['name'];
    });

Як написано в документації на php :

Оскільки foreach покладається на внутрішній покажчик масиву в PHP 5, зміна його в циклі може призвести до несподіваної поведінки.

У PHP 7 foreach не використовує внутрішній покажчик масиву.


Зауважте, що 3-й параметр повинен бути ARRAY_FILTER_USE_KEY, щоб передати ключ тут як $ e.
namezero

@namezero ОК, чому це тут важливо?
AbraCadaver

@AbraCadaver З документації ( php.net/manual/en/function.array-filter.php ): ARRAY_FILTER_USE_KEY - pass key as the only argument to callback instead of the value ARRAY_FILTER_USE_BOTH - pass both value and key as arguments to callback instead of the value Default is 0 which will pass value as the only argument to callback instead. Це сказало, прочитавши відповідь ще раз у цьому випадку, звичайно, це не матиме значення, як ви заявляєте.
namezero

Важливо Якщо ви хочете зберегти масив як упорядкований масив, вам потрібно зателефонувати display_related_tags = array_values(display_related_tags);після нього.
guyaloni

9
foreach($display_related_tags as $key => $tag_name)
{
    if($tag_name == $found_tag['name'])
        unset($display_related_tags[$key];
}

3
'unlink' від’єднує файли, це не має нічого спільного зі змінними або, точніше, масивами. Можливо, ви маєте на увазі «невдалий»?
amn

6

Замість того, щоб робити цикл foreach () на масиві, було б швидше скористатися array_search () для пошуку потрібного ключа. На малих масивах я б хотів з foreach для кращої читальності, але для більших масивів або часто виконуваного коду це має бути трохи більш оптимальним:

$result=array_search($unwantedValue,$array,true);
if($result !== false) {
  unset($array[$result]);   
}

Необхідний суворий оператор порівняння! ==, тому що array_search () може повернути 0 як індекс $ neželjeноїValue.

Крім того, вищенаведений приклад видалить лише перше значення $ neželjeноїValue, якщо $ unantedValue може виникнути більше, ніж один раз у масиві $, слід знайти array_keys (), щоб знайти їх усі:

$result=array_keys($array,$unwantedValue,true)
foreach($result as $key) {
  unset($array[$key]);
}

Перегляньте http://php.net/manual/en/function.array-search.php для отримання додаткової інформації.


0

якщо у вас є сценарій, у якому вам доведеться видалити більше, ніж одне значення з масиву foreach, у цьому випадку ви повинні передати значення за посиланням для кожного: Я намагаюся пояснити цей сценарій:

foreach ($manSkuQty as $man_sku => &$man_qty) {

               foreach ($manufacturerSkus as $key1 => $val1) {

  // some processing here and unset first loops entries                     
 //  here dont include again for next iterations
                           if(some condition)
                            unset($manSkuQty[$key1]);

                        }
               }
}

у другому циклі ви хочете зняти записи перших циклів, щоб вони не поверталися знову в ітерації з метою виконання, а потім знімалися з пам'яті, тому що в пам'яті вони присутні і будуть ітераціями.


0

Вже є відповіді, які висвітлюють, як зняти налаштування. Замість того, щоб повторювати код у всіх класах, виконайте функцію, як показано нижче, та використовуйте її в коді, коли це потрібно. У бізнес-логіці іноді не хочеться викривати деякі властивості. Щоб видалити, перегляньте нижче один виклик лайнера

public static function removeKeysFromAssociativeArray($associativeArray, $keysToUnset)
{
    if (empty($associativeArray) || empty($keysToUnset))
        return array();

    foreach ($associativeArray as $key => $arr) {
        if (!is_array($arr)) {
            continue;
        }

        foreach ($keysToUnset as $keyToUnset) {
            if (array_key_exists($keyToUnset, $arr)) {
                unset($arr[$keyToUnset]);
            }
        }
        $associativeArray[$key] = $arr;
    }
    return $associativeArray;
}

Телефонуйте як:

removeKeysFromAssociativeArray($arrValues, $keysToRemove);

-1

Як уже згадувалося, ви хочете зробити передбачення з ключем і скасувати використання ключа, але зауважте, що мутація масиву під час ітерації - це погана ідея, хоча я не впевнений у правилах PHP щодо цього віддалено.


2
Незалежно від цілого масиву виконуватиметься php foreach. Перевірте встановлення значення, наступного за ітерацією. Він буде повторюватись при зміщенні, але значення буде нульовим.
Кевін Пено

Якщо ви не мутуєте масив під час ітерації, то як взагалі мутувати масив? Можуть бути середніми foreachчи forконструкціями замість ітерації взагалі?
Герман

Це скоріше коментар до іншої відповіді, ніж відповідь сама по собі.
Зловісна Борода
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.