Usuwanie pozycji tablicy według wartości

166

Muszę usunąć element tablicy o podanej wartości:

if (in_array($id, $items)) {
    $items = array_flip($items);
    unset($items[ $id ]);
    $items = array_flip($items);
}

Czy można to zrobić w krótszy (bardziej efektywny) sposób?

Marek
źródło

Odpowiedzi:

423

Można to osiągnąć za pomocą prostego jednowierszowego.

Mając tę ​​tablicę:

$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'));

A wartość $arrbędzie:

array('nice_item', 'another_liked_item')

Mam nadzieję, że pomoże to napisać piękny kod.

Alejandro García Iglesias
źródło
2
Nie, to nie współpracuje z tablicami odwołuje The array_difffunkcja jest nieinwazyjne, zwraca nową tablicę.
Alejandro García Iglesias,
2
@srcspider, czemu nie? $referenced = array_diff($referenced, $items_to_remove);
Alejandro García Iglesias
1
$ referencja wskazuje teraz na nową tablicę, tablica, którą chciałeś zmienić, nadal ma stare wartości.
srcspider
2
@srcspider no cóż, powiedz mi, co się tutaj dzieje ... codepad.org/11ZhiFP0
Alejandro García Iglesias
1
mój błąd; sztuczka aliasingu zmiennego php zawsze mi
przeszkadza
37

Dodaję drugą odpowiedź. Napisałem szybki skrypt testowy, aby wypróbować tutaj różne metody.

$arr = array(0 => 123456);
for($i = 1; $i < 500000; $i++) {
    $arr[$i] = rand(0,PHP_INT_MAX);
}

shuffle($arr);
$arr2 = $arr;
$arr3 = $arr;

/** 
 * Method 1 - array_search()
 */
$start = microtime(true);
while(($key = array_search(123456,$arr)) !== false) {
    unset($arr[$key]);
}
echo count($arr). ' left, in '.(microtime(true) - $start).' seconds<BR>';

/** 
 * Method 2 - basic loop
 */
$start = microtime(true);
foreach($arr2 as $k => $v) {
    if ($v == 123456) {
        unset($arr2[$k]);
    }
}
echo count($arr2). 'left, in '.(microtime(true) - $start).' seconds<BR>';

/** 
 * Method 3 - array_keys() with search parameter
 */
$start = microtime(true);
$keys = array_keys($arr3,123456);
foreach($keys as $k) {
    unset($arr3[$k]);
}
echo count($arr3). 'left, in '.(microtime(true) - $start).' seconds<BR>';

Trzecia metoda, array_keys()z określonym opcjonalnym parametrem wyszukiwania, wydaje się zdecydowanie najlepszą metodą. Przykład danych wyjściowych:

499999 left, in 0.090957164764404 seconds
499999left, in 0.43156313896179 seconds
499999left, in 0.028877019882202 seconds

Sądząc po tym, rozwiązaniem, którego wtedy użyłbym, byłoby:

$keysToRemove = array_keys($items,$id);
foreach($keysToRemove as $k) {
    unset($items[$k]);
}
zombat
źródło
Myślę, że array_search jest znacznie bardziej czytelnym kodem niż użycie metody array_diff. Upvote
kendepelchin
@zombat Zastanawiam się, czy kolejność ma coś wspólnego z wynikami. Możliwe, że shuffle umieści szukaną wartość bliżej początku lub końca. Poza tym ... +1
General Redneck
31

Co powiesz na:

if (($key = array_search($id, $items)) !== false) unset($items[$key]);

lub dla wielu wartości:

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

Zapobiegałoby to również utracie klucza, co jest efektem ubocznym array_flip().

zombat
źródło
1
nie zadziała, jeśli $ id jest pierwszym elementem tablicy, lepiej w ten sposób: if (($ key = array_search ($ id, $ items))! == false) unset ($ items [$ key]);
Marek
15

usunąć $rm_valz$arr

unset($arr[array_search($rm_val, $arr)]);
Toma
źródło
8

Najpotężniejszym rozwiązaniem byłoby użycie array_filter, które pozwala zdefiniować własną funkcję filtrowania.

Ale niektórzy mogą powiedzieć, że to trochę przesada, w twojej sytuacji ...
Prosta foreachpętla, aby przejść przez tablicę i usunąć element, którego nie chcesz, powinna wystarczyć.

Coś takiego w twoim przypadku powinno prawdopodobnie załatwić sprawę:

foreach ($items as $key => $value) {
    if ($value == $id) {
        unset($items[$key]);
        // If you know you only have one line to remove, you can decomment the next line, to stop looping
        //break;
    }
}
Pascal MARTIN
źródło
6

Wypróbuj array_search ()

Savageman
źródło
3
Właśnie przeczytałem dokumentację i zalecam użycie array_keys () do znalezienia wszystkich kluczy powiązanych z wartością.
Savageman
@Savageman - Zgoda. Przeprowadziłem szybki test porównawczy i array_keys()wydaje się, że działa lepiej niż array_search()w tym zadaniu.
zombat
6

Twoje rozwiązania działają tylko wtedy, gdy masz w tablicy unikalne wartości

Widzieć:

<?php
$trans = array("a" => 1, "b" => 1, "c" => 2);
$trans = array_flip($trans);
print_r($trans);
?>

Lepszym sposobem byłoby wyłączenie funkcji array_search , w razie potrzeby w pętli.

Dutow
źródło
masz rację, ale w tym konkretnym przypadku jestem pewien, że wartości są wyjątkowe :)
Marek
5

bez klapki:

<?php
foreach ($items as $key => $value) {
    if ($id === $value) {
        unset($items[$key]);
    }
}
erenon
źródło
5
function deleteValyeFromArray($array,$value)
{
   foreach($array as $key=>$val)
   {
      if($val == $value)
      {
         unset($array[$key]);
      }
   }
   return $array;
}
Suman Biswas
źródło
4

Możesz użyć funkcji array_splice dla tej operacji Ref: array_splice

array_splice($array, array_search(58, $array ), 1);
Tejas Soni
źródło