PHP массив удалить по значению (не ключу)

711

У меня есть массив PHP следующим образом:

$messages = [312, 401, 1599, 3, ...];

Я хочу удалить элемент, содержащий значение $del_val (например, $del_val=401), но я не знаю его ключа. Это может помочь: каждое значение может быть только один раз.

Я ищу простейшую функцию для выполнения этой задачи.

  • 1
    @Adam Strudwick Но если у вас есть много удалений в этом массиве, было бы лучше, чтобы повторить его один раз и сделать его ключ таким же, как значение?
  • 0
    Тот же вопрос: stackoverflow.com/questions/1883421/…
Показать ещё 1 комментарий
Теги:
arrays

25 ответов

1262
Лучший ответ

Используя array_search() и unset, попробуйте следующее:

if (($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
}

array_search() возвращает ключ найденного элемента, который может быть использован для удаления этого элемента из исходного массива с помощью unset(). Он вернет FALSE при сбое, однако он может вернуть значение false-y при успешном завершении (например, ваш ключ может быть 0), поэтому используется оператор строгого сравнения !==.

Оператор if() будет проверять, вернет ли значение array_search() значение, и выполнит действие только в том случае, если оно было выполнено.

  • 12
    Будет ли работать $ messages = array_diff ($ messages, array ($ del_val))? Будет ли лучше по производительности?
  • 9
    @ Adam Почему бы не проверить это? Мне кажется, что array_diff() будет медленнее, так как он сравнивает два массива, а не просто ищет один, например, array_search() .
Показать ещё 19 комментариев
462

Ну, удаляя элемент из массива, в основном просто устанавливается разница с одним элементом.

array_diff( [312, 401, 15, 401, 3], [401] ) // removing 401 returns [312, 15, 3]

Он отлично делится, вы можете удалить столько элементов, сколько хотите, если хотите.

Отказ от ответственности: обратите внимание, что мое решение создает новую копию массива, сохраняя прежнюю неповрежденную, в отличие от принятого ответа, который мутирует. Из-за этого это может быть немного медленнее.

  • 27
    это работает только для объектов, которые могут быть преобразованы в строку
  • 7
    Кажется, я получаю «Parse Error» за высказывание [$element] , вместо этого я использовал array($element) . Не важно, а просто хотел, чтобы любой, у кого была похожая проблема, знал, что они не одни
Показать ещё 15 комментариев
97

Один интересный способ - использовать array_keys():

foreach (array_keys($messages, 401, true) as $key) {
    unset($messages[$key]);
}

Функция array_keys() принимает два дополнительных параметра, чтобы возвращать только ключи для определенного значения и требуется ли строгая проверка (т.е. использование == = для сравнения).

Это также может удалить несколько элементов массива с тем же значением (например, [1, 2, 3, 3, 4]).

  • 3
    @ blasteralfredΨ Линейный поиск - O (n); Я не уверен, почему вы, кажется, думаете, что это проблема.
  • 1
    Да, это эффективно для выбора нескольких элементов / ключей массива.
Показать ещё 3 комментария
43

Если вы знаете, что ваш массив будет содержать только один элемент с этим значением, вы можете сделать

$key = array_search($del_val, $array);
if (false !== $key) {
    unset($array[$key]);
}

Если, однако, ваше значение может произойти более одного раза в вашем массиве, вы можете сделать это

$array = array_filter($array, function($e) use ($del_val) {
    return ($e !== $del_val);
});

Примечание. Второй вариант работает только для PHP5.3 + с Closures

35
$fields = array_flip($fields);
unset($fields['myvalue']);
$fields = array_flip($fields);
  • 9
    Это работает только тогда, когда ваш массив не содержит повторяющихся значений, кроме тех, которые вы пытаетесь удалить.
  • 1
    @jberculo и иногда это именно то, что вам нужно, в некоторых случаях это спасает меня от создания уникального массива на нем aswel
Показать ещё 4 комментария
22

Посмотрите на следующий код:

$arr = array('nice_item', 'remove_me', 'another_liked_item', 'remove_me_also');

Вы можете сделать:

$arr = array_diff($arr, array('remove_me', 'remove_me_also'));

И это даст вам этот массив:

array('nice_item', 'another_liked_item')
  • 0
    это работает с ассоциативными массивами?
  • 1
    Для ассоциативных массивов вы должны использовать array_diff_assoc ()
Показать ещё 1 комментарий
18

Лучший способ - array_splice

array_splice($array, array_search(58, $array ), 1);

Причина для лучшего находится здесь: http://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/

  • 3
    Это не будет работать с ассоциативными массивами и массивами, у которых есть пробелы в их ключах, например [1, 2, 4 => 3] .
  • 0
    Нет, извините, это сработает. Пожалуйста, прочитайте статью, которую я предоставил ссылку
Показать ещё 2 комментария
18

В следующем коде повторяющиеся значения будут удалены из сообщений $.

$messages = array_diff($messages, array(401));

  • 3
    Up-голосование. Это был уже среди других ответов, но вы говорите это лучше, оставляя это простым, как у вас. Ответ просто "array_diff"
  • 0
    Выглядит просто, но это меняет сложность с O (n) на O (n lg n). Так что на самом деле все сложнее;)
15

Или просто, ручной способ:

foreach ($array as $key => $value){
    if ($value == $target_value) {
        unset($array[$key]);
    }
}

Это самый безопасный из них, потому что вы полностью контролируете свой массив

  • 1
    Использование array_splice() вместо unset() также переупорядочит индексы массива, что может быть лучше в этом случае.
9
function array_remove_by_value($array, $value)
{
    return array_values(array_diff($array, array($value)));
}

$array = array(312, 401, 1599, 3);

$newarray = array_remove_by_value($array, 401);

print_r($newarray);

Выход

Array ( [0] => 312 [1] => 1599 [2] => 3 )

  • 2
    Это решение реорганизовать индекс, хорошая работа.
  • 1
    Я не уверен, что это быстрее, так как это решение включает в себя несколько вызовов функций.
7

вы можете сделать:

unset($messages[array_flip($messages)['401']]);

Объяснение: Удалите элемент с ключом 401 после переключения массива.

  • 0
    Вы должны быть очень осторожны, если хотите сохранить государство. потому что весь будущий код должен иметь значения вместо ключей.
  • 1
    Массив @saadlulu $ messages не будет перевернут, так как array_flip () не влияет на исходный массив, поэтому результирующий массив после применения предыдущей строки будет таким же, за исключением того, что нежелательный результат будет удален.
Показать ещё 1 комментарий
7

Если у вас есть > php5.3, есть один код строки:

$array = array_filter($array, function($i) use ($value){return $i != $value;}); 
  • 0
    Уверены ли вы? Это замыкание не имеет доступа к $value , поэтому его нужно поместить в мини-класс, чтобы вы могли получить доступ к $value внутри замыкания ....
  • 0
    @cale_b, я обновил пример. Также вот ссылка: php.net/manual/en/functions.anonymous.php
Показать ещё 1 комментарий
7

Чтобы удалить несколько значений, попробуйте выполнить этот

while (($key = array_search($del_val, $messages)) !== false) 
{
    unset($messages[$key]);
}
5

Заимствовал логику underscoreJS _.reject и создал две функции (люди предпочитают функции!!)

array_reject_value: Эта функция просто отвергает указанное значение (также работает для PHP4,5,7)

function array_reject_value(array &$arrayToFilter, $deleteValue) {
    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if ($value !== $deleteValue) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

array_reject: Эта функция просто отвергает метод вызова (работает для PHP >= 5.3)

function array_reject(array &$arrayToFilter, callable $rejectCallback) {

    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if (!$rejectCallback($value, $key)) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

Итак, в нашем текущем примере мы можем использовать приведенные выше функции следующим образом:

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject_value($messages, 401);

или даже лучше: (поскольку это дает нам лучший синтаксис для использования, например array_filter)

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject($messages, function ($value) {
    return $value === 401;
});

Вышеприведенное может быть использовано для более сложных вещей, например, скажем, мы хотели бы удалить все значения, которые больше или равны 401, мы могли бы просто сделать это:

$messages = [312, 401, 1599, 3, 6];
$greaterOrEqualThan = 401;
$messages = array_reject($messages, function ($value) use $greaterOrEqualThan {
    return $value >= $greaterOrEqualThan;
});
  • 1
    Разве это не изобретательский фильтр? php.net/manual/en/function.array-filter.php
  • 0
    Да, в самом деле. Как я уже говорил в посте "или даже лучше: (так как это дает нам лучший синтаксис для использования, как у array_filter)". Иногда вам просто нужно, чтобы функция отклоняла как подчеркивание, и это на самом деле просто противоположность фильтра (и вам нужно получить ее с как можно меньшим количеством кода). Это то, что делают функции. Это простой способ отклонить значения.
4

@Ответ на Боянгл помог мне. Спасибо.

В моем случае массив может быть ассоциативным или нет, поэтому я добавил эту функцию

function test($value, $tab) {

 if(($key = array_search($value, $tab)) !== false) {
    unset($tab[$key]); return true;

 } else if (array_key_exists($value, $tab)){
        unset($tab[$value]); return true;

 } else {
    return false; // the $value is not in the array $tab
 }

}

Привет

4

Получить ключ с array_search().

  • 2
    Как мне удалить значение IF и только если я найду его с помощью array_search?
  • 2
    $ k = array_search ($ needle, $ haystack, true); if ($ k! == false) {unset ($ haystack [$ k]); }
3

В соответствии с вашим требованием " каждое значение может быть только один раз", если вы просто заинтересованы в сохранении уникальных значений в своем массиве, тогда array_unique() может быть то, что вы ищете.

Ввод:

$input = array(4, "4", "3", 4, 3, "3");
$result = array_unique($input);
var_dump($result);

Результат:

array(2) {
  [0] => int(4)
  [2] => string(1) "3"
}
3

ОК.. Я знаю, что это неэффективно, но просто, интуитивно понятно и легко читается.
Поэтому, если кто-то ищет не очень причудливое решение, которое может быть расширено для работы с большим количеством значений или более конкретных условий.. вот простой код:

$result = array();
$del_value = 401;
//$del_values = array(... all the values you don`t wont);

foreach($arr as $key =>$value){
    if ($value !== $del_value){
        $result[$key] = $value;
    }

    //if(!in_array($value, $del_values)){
    //    $result[$key] = $value;
    //}

    //if($this->validete($value)){
    //      $result[$key] = $value;
    //}
}

return $result
3

Если ваши значения, которые вы хотите удалить, являются или могут находиться в массиве. Используйте функцию array_diff. Кажется, отлично работает для таких вещей.

array_diff

$arrayWithValuesRemoved = array_diff($arrayOfData, $arrayOfValuesToRemove);
3

Если вы не знаете его ключ, это означает, что это не имеет значения.

Вы можете поместить значение в качестве ключа, это означает, что он мгновенно найдет значение. Лучше, чем использовать поиск во всех элементах снова и снова.

$messages=array();   
$messages[312] = 312;    
$messages[401] = 401;   
$messages[1599] = 1599;   
$messages[3] = 3;    

unset($messages[3]); // no search needed
  • 0
    Работает только для объектов, которые могут быть преобразованы в строку.
2

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

if(($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
    $arr = array_values($messages);
}

Ссылка здесь

2

Или однострочный оператор с использованием оператора or:

($key = array_search($del_val, $messages)) !== false or unset($messages[$key]);
1

одиночный код линейки (спасибо array_diff()), используйте следующее:

$messages = array_diff($messages, array(401));
1

вы можете ссылаться на этот URL:   для функции

array-diff-key()

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_diff_key($array1, $array2));
?>

Тогда вывод должен быть,

array(2) {
  ["red"]=>
  int(2)
  ["purple"]=>
  int(4)
}
0

Еще одна идея удалить значение массива, используйте array_diff. Если я хочу

$my_array = array(1=>"a", "second_value"=>"b", 3=>"c", "d");
$new_array_without_value_c = array_diff($my_array, array("c"));

(Doc: http://php.net/manual/fr/function.array-diff.php)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню