Usuń tablicę PHP według wartości (nie klucza)


885

Mam tablicę PHP w następujący sposób:

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

Chcę usunąć element zawierający wartość $del_val(na przykład $del_val=401), ale nie znam jego klucza. Może to pomóc: każda wartość może być tam tylko raz .

Proszę o najprostszą funkcję do wykonania tego zadania.


1
@Adam Strudwick Ale jeśli masz wiele usunięć z tej tablicy, czy lepiej byłoby powtórzyć ją raz i uczynić jej klucz identycznym z wartością?
dzona


możliwy duplikat PHP Usuń element z tablicy
Alex

Odpowiedzi:


1565

Używając array_search()i unset, spróbuj wykonać następujące czynności:

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

array_search()zwraca klucz znalezionego elementu, którego można użyć do usunięcia tego elementu z oryginalnej tablicy za pomocą unset(). Wróci FALSEpo awarii, jednak w przypadku sukcesu może zwrócić wartość fałsz-y ( 0na przykład kluczem ), dlatego !==używany jest operator ścisłego porównania .

if()Oświadczenie sprawdzi, czy array_search()zwrócony wartość i będzie wykonywać jedynie działania, jeśli tak się stało.


14
Czy $ messages = array_diff ($ messages, array ($ del_val)) też działałoby? Czy byłby lepszy w działaniu?
Adam Strudwick,

9
@Adam Dlaczego nie przetestować? Mam wrażenie, że array_diff()byłoby wolniej, ponieważ porównuje dwie tablice, a nie tylko przeszukuje jedną podobną array_search().
Bojangles,

22
Mimo że jest to poprawne, należy unikać przypisywania wartości w takich instrukcjach. Doprowadzi cię to tylko do kłopotów.
adlawson,

17
Co jeśli $keyjest 0?
evan

16
Jeśli 0szukana wartość ma klucz lub inną wartość falsey, nie rozbroi tej wartości, a kod nie będzie działał. Powinieneś przetestować $key === false. (edytuj - masz to)
evan

671

Cóż, usunięcie elementu z tablicy jest w zasadzie tylko różnicą dla jednego elementu.

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

Ładnie się uogólnia, jeśli chcesz, możesz jednocześnie usunąć tyle elementów, ile chcesz.

Uwaga: Zauważ, że moje rozwiązanie tworzy nową kopię tablicy, zachowując starą nietkniętą w przeciwieństwie do przyjętej odpowiedzi, która mutuje. Wybierz ten, którego potrzebujesz.


32
działa to tylko w przypadku obiektów, które można przekonwertować na ciąg znaków
nischayn22,

7
Wydaje mi się, że pojawia się „Błąd analizy”, mówiąc [$element], użyłem array($element)zamiast tego. Żaden biggie, ale chciał tylko, aby każdy, kto miał podobny problem, wiedział, że nie był sam
Angad

8
Jasne, założyłem, że PHP 5.4 ma teraz większość porzucenia starej notacji. Dziękuję za uwagę.
Rok Kralj

22
Warto zauważyć, że z jakiegoś powodu array_diffużywa (string) $elem1 === (string) $elem2jako warunku równości, a nie $elem1 === $elem2jak można się spodziewać. Problem wskazany przez @ nischayn22 jest tego konsekwencją. Jeśli chcesz użyć czegoś jako funkcji narzędzia, która będzie działać dla tablic dowolnych elementów (które mogą być obiektami), odpowiedź Bojangle może być lepsza z tego powodu.
Mark Amery

4
Zauważ również, że ta metoda wykonuje sortowanie wewnętrznie dla każdego argumentu, array_diff()a zatem przesuwa środowisko wykonawcze do O (n lg n) z O (n).
Ja͢ck

115

Ciekawym sposobem jest użycie array_keys():

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

array_keys()Funkcja przyjmuje dwa dodatkowe parametry, aby wrócić tylko klucze do określonej wartości i czy wymagana jest ścisła kontrola (czyli używając === dla porównania).

Może to również usunąć wiele elementów tablicy o tej samej wartości (np [1, 2, 3, 3, 4].).


3
@ blasteralfredΨ Wyszukiwanie liniowe to O (n); Nie jestem pewien, dlaczego wydaje ci się, że to problem.
Ja͢ck

1
Tak, jest to skuteczne przy wyborze wielu elementów / kluczy tablicy.
Oki Erie Rinaldi

3
Jest to najlepsze rozwiązanie dla tablic, które mogą nie zawierać wszystkich unikalnych wartości.
Derokorian

Problem polega na tym, że pozostawia on indeks kluczy po kolei: [0] - a, [2] - b ([1] zniknął, ale tablica wciąż go nie ma)
Rodniko

3
@Rodniko, w którym to przypadku również będziesz potrzebować array_values(); pozostałe klucze są nadal w tej samej kolejności, więc technicznie nie jest to „nieposortowane”
Ja͢ck

55

Jeśli wiesz na pewno, że tablica będzie zawierała tylko jeden element o tej wartości, możesz to zrobić

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

Jeśli jednak twoja wartość może wystąpić więcej niż jeden raz w tablicy, możesz to zrobić

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

Uwaga: druga opcja działa tylko dla PHP 5.3 + z zamknięciami


41
$fields = array_flip($fields);
unset($fields['myvalue']);
$fields = array_flip($fields);

11
Działa to tylko wtedy, gdy tablica nie zawiera zduplikowanych wartości innych niż te, które próbujesz usunąć.
jberculo

2
@jberculo, a czasem dokładnie to, czego potrzebujesz, w niektórych przypadkach oszczędza mi robienie tablicy unikatowej na nim aswel
DarkMukke

Może, ale użyłbym do tego specjalnie zaprojektowanych funkcji, zamiast być tylko szczęśliwym efektem ubocznym funkcji, która jest zasadniczo używana i przeznaczona do czegoś innego. Sprawiłoby to również, że Twój kod byłby mniej przejrzysty.
jberculo

Komunikat mówi „każda wartość może być tam tylko raz”, to powinno działać. Byłoby miło, gdyby plakat użył nazw zmiennych smae i dodał trochę wyjaśnień
Raatje

2
najwyraźniej jest to najszybszy w porównaniu do wybranego rozwiązania, zrobiłem małe testy porównawcze.
AMB,

28

Spójrz na następujący kod:

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

Możesz to zrobić:

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

I to da ci tę tablicę:

array('nice_item', 'another_liked_item')

1
W przypadku tablic asocjacyjnych należy użyć array_diff_assoc ()
theCodeMachine

5
Czym różni się to od tej odpowiedzi ?
random_user_name

26

Najlepszym sposobem jest array_splice

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

Powód najlepszego znajduje się tutaj: http://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/


4
Nie zadziała to na tablicach asocjacyjnych i tablicach, które mają luki w swoich kluczach, np [1, 2, 4 => 3].
Ja͢ck

Nie przepraszam, to zadziała. Proszę przeczytać artykuł, który podałem link
Airy

4
Nie będzie. Rozważ tablicę mojego powyższego komentarza; kiedy użyję twojego kodu do usunięcia wartości 3, tablica będzie [1, 2, 3]; innymi słowy, wartość nie została usunięta. Żeby było jasne, nie mówię, że zawodzi we wszystkich scenariuszach, tylko w tym jednym.
Ja͢ck

1
array_splice to najlepsza metoda, unset nie zmieni indeksów tablicy po usunięciu
Raaghu

21

Lub po prostu ręczny sposób:

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

Jest to najbezpieczniejszy z nich, ponieważ masz pełną kontrolę nad tablicą


1
Użycie array_splice()zamiast unset()spowoduje zmianę kolejności indeksów tablic, co może być lepsze w tym przypadku.
Daniele Orlando,

20

Poniższy kod spowoduje, że powtarzające się wartości zostaną usunięte z wiadomości $.

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


3
Podwyższony głos. Było już wśród innych odpowiedzi, ale mówisz to najlepiej, utrzymując prostotę, tak jak masz. Odpowiedź brzmi: „array_diff”
ghbarratt

1
Wygląda prosto, ale zmienia złożoność z O (n) na O (n lg n). Tak więc jest to bardziej skomplikowane;)
Krzysztof Przygoda

20

Jeśli masz PHP 5.3+, jest jeden kod wiersza:

$array = array_filter($array, function ($i) use ($value) { return $i !== $value; }); 

Jesteś pewny? To zamknięcie nie ma dostępu $value, więc naprawdę musi zostać umieszczone w mini klasie, abyś mógł uzyskać dostęp $valuew zamknięciu ....
random_user_name

@cale_b, zaktualizowałem przykład. Oto także ref: php.net/manual/en/functions.anonymous.php
David Lin

3
Równie dobrze możesz napisać całą bazę kodu na jednej linii, jeśli nazwiesz ten „kodem jednej linii”
Milan Simek,

16
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);

Wynik

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


2
nie jestem pewien, czy jest to szybsze, ponieważ to rozwiązanie obejmuje wiele wywołań funkcji.
Julian Paolo Dayag,

13

możesz to zrobić:

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

Objaśnienie : Usuń element, który ma klucz 401po odwróceniu tablicy.


Musisz być bardzo ostrożny, jeśli chcesz zachować stan. ponieważ cały przyszły kod będzie musiał mieć wartości zamiast kluczy.
saadlulu

1
Tablica @saadlulu $ messages nie zostanie odwrócona, ponieważ array_flip () nie wpływa na oryginalną tablicę, więc tablica wynikowa po zastosowaniu poprzedniej linii będzie taka sama, z tym że niechciany wynik zostanie usunięty.
Qurashi

2
nie jestem pewien, czy jest to poprawne, co jeśli jest kilka elementów o wartości 401?
Zippp,

To nadal zachowa klucze.
Szabolcs Páll

8

Aby usunąć wiele wartości, spróbuj tego:

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

6

Zapożyczył logikę podkreślenia.JS _.reject i utworzył dwie funkcje (ludzie wolą funkcje !!)

array_reject_value: Ta funkcja po prostu odrzuca podaną wartość (działa również dla 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: Ta funkcja po prostu odrzuca metodę wywoływania (działa dla 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;
}

W naszym obecnym przykładzie możemy użyć powyższych funkcji w następujący sposób:

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

lub nawet lepiej: (ponieważ daje nam to lepszą składnię do użycia jak na przykład array_filter )

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

Powyższe może być użyte do bardziej skomplikowanych rzeczy, takich jak powiedzmy, że chcielibyśmy usunąć wszystkie wartości, które są większe lub równe 401, moglibyśmy to po prostu zrobić:

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


W rzeczy samej. Jak już mówię w poście „lub nawet lepiej: (ponieważ daje nam to lepszą składnię, taką jak w przypadku argumentu array_filter)”. Czasami naprawdę musisz po prostu mieć funkcję odrzucania jako podkreślenia i jest to naprawdę przeciwieństwo filtru (i musisz uzyskać ją z jak najmniejszą ilością kodu). To właśnie robią funkcje. Jest to prosty sposób na odrzucenie wartości.
John Skoumbourdis,

6
$array = array("apple", "banana",'mango');
$array = array_filter($array, function($v) { return $v != "apple"; });

Spróbuj tego, jest to najlepszy i najszybszy sposób na usunięcie elementu według wartości


5

Odpowiedź @Bojangles pomogła mi. Dziękuję Ci.

W moim przypadku tablica może być asocjacyjna lub nie, więc dodałem następującą funkcję

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
 }

}

pozdrowienia



4

Zaakceptowana odpowiedź konwertuje tablicę na tablicę asocjacyjną, więc jeśli chcesz zachować ją jako tablicę niepowiązaną z zaakceptowaną odpowiedzią, być może będziesz musiał użyć array_valuesrównież.

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

Referencje są tutaj


4

Zgodnie z twoim wymaganiem „ każda wartość może istnieć tylko raz ”, jeśli chcesz zachować unikalne wartości w tablicy, array_unique()może być tym, czego szukasz.

Wejście:

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

Wynik:

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


4

Wiem, że to wcale nie jest wydajne, ale jest proste, intuicyjne i łatwe do odczytania.
Jeśli więc ktoś szuka nie tak wymyślnego rozwiązania, które można rozszerzyć do pracy z większymi wartościami lub bardziej szczegółowymi warunkami ... oto prosty kod:

$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

4

Uzyskaj klucz tablicy za pomocą array_search().


2
Jak usunąć wartość JEŻELI i tylko wtedy, gdy znajdę ją za pomocą tablicy_wyszukiwania?
Adam Strudwick

3
$ k = array_search ($ igła, $ stóg siana, prawda); if ($ k! == false) {unset ($ stóg siana [$ k]); }
evan

3

Jeśli nie znasz jego klucza, oznacza to, że to nie ma znaczenia.

Możesz umieścić wartość jako klucz, co oznacza, że ​​natychmiast znajdzie wartość. Lepsze niż wyszukiwanie we wszystkich elementach w kółko.

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

unset($messages[3]); // no search needed

Działa tylko w przypadku obiektów, które można przekonwertować na ciąg.
Emile Bergeron,

2

One-liner z oroperatorem:

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

2

możesz odwołać się do tego adresu URL : dla funkcji

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));
?>

Zatem wyjście powinno być

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


1

Myślę, że najprostszym sposobem byłoby użycie funkcji z pętlą foreach:

//This functions deletes the elements of an array $original that are equivalent to the value $del_val
//The function works by reference, which means that the actual array used as parameter will be modified.

function delete_value(&$original, $del_val)
{
    //make a copy of the original, to avoid problems of modifying an array that is being currently iterated through
    $copy = $original;
    foreach ($original as $key => $value)
    {
        //for each value evaluate if it is equivalent to the one to be deleted, and if it is capture its key name.
        if($del_val === $value) $del_key[] = $key;
    };
    //If there was a value found, delete all its instances
    if($del_key !== null)
    {
        foreach ($del_key as $dk_i)
        {
            unset($original[$dk_i]);
        };
        //optional reordering of the keys. WARNING: only use it with arrays with numeric indexes!
        /*
        $copy = $original;
        $original = array();
        foreach ($copy as $value) {
            $original[] = $value;
        };
        */
        //the value was found and deleted
        return true;
    };
    //The value was not found, nothing was deleted
    return false;
};

$original = array(0,1,2,3,4,5,6,7,4);
$del_val = 4;
var_dump($original);
delete_value($original, $del_val);
var_dump($original);

Dane wyjściowe będą:

array(9) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [4]=>
  int(4)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
  [8]=>
  int(4)
}
array(7) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
}

1

W PHP 7.4 za pomocą funkcji strzałek:

$messages = array_filter($messages, fn ($m) => $m != $del_val);

Aby zachować tablicę niesocjacyjną, zawiń ją array_values():

$messages = array_values(array_filter($messages, fn ($m) => $m != $del_val));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.