Как удалить элемент массива в цикле 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
Обратите внимание, что индексированные массивы с неустановленными элементами могут быть представлены как объекты вместо массивов после a json_encode(). Вы можете решить эту проблему с помощью $display_related_tags = array_values ($display_related_tags);after the foreachloop.
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 не использует указатель внутреннего массива.


Обратите внимание, что третий параметр должен быть ARRAY_FILTER_USE_KEY, чтобы передать ключ как $ e здесь.
namezero 05

@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);его после него.
гуялони,

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 в качестве индекса $ unwantedValue.

Кроме того, в приведенном выше примере будет удалено только первое значение $ unwantedValue, если $ unwantedValue может встречаться более одного раза в массиве $, вы должны использовать 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

Как уже упоминалось, вы хотите выполнить foreach с ключом и отключить его с помощью ключа, но обратите внимание, что изменение массива во время итерации в целом является плохой идеей, хотя я не уверен в правилах PHP по этому поводу. экспромтом.


2
PHP foreach будет выполняться для всего массива независимо. Протестируйте сброс значения, которое будет следующим в итерации. Он будет повторять смещение, но значение будет нулевым.
Кевин Пено,

Если вы не изменяете массив во время итерации, то как вообще изменять массив? Может быть означает foreachили forконструкции вместо итерации вообще?
Gherman

Это больше комментарий к другому ответу, чем ответ сам по себе.
Sinister Beard
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.