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