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.