2009-12-10 17 views
143

Devo rimuovere oggetto array con valore dato:Rimozione elemento dell'array per valore

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

Potrebbe essere fatto in breve modo (più efficiente)?

+1

Eventuali duplicati di [array PHP cancellare per valore (non chiave)] (http://stackoverflow.com/questions/7225070/php-array-delete-by-value-not-key) – Ben

risposta

384

Esso può essere realizzato con una semplice linea.

Avere questa matrice:

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

si può fare:

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

E il valore di $arr sarà:

array('nice_item', 'another_liked_item') 

speriamo vi sia utile scrivere codice bello.

+0

Solo se si ha il controllo della variabile. Se lo hai ricevuto come riferimento, questo metodo è inutilizzabile. – srcspider

+1

No, funziona * con gli array di riferimento, la funzione 'array_diff' non è distruttiva, restituisce una nuova matrice. –

+0

Ti manca il mio punto, se tu avessi un array per riferimento e volessi rimuovere un oggetto da esso, non potresti farlo con questo metodo. – srcspider

4
+3

Ho appena letto la documentazione e consiglio di utilizzare un rray_keys() per trovare tutte le chiavi associate a un valore. – Savageman

+0

@ Savageman: concordato. Ho eseguito un rapido benchmark e 'array_keys()' sembra funzionare meglio di 'array_search()' per questa attività. – zombat

5

w/o capovolgere:

<?php 
foreach ($items as $key => $value) { 
    if ($id === $value) { 
     unset($items[$key]); 
    } 
} 
7

La soluzione più potente sarebbe utilizzando array_filter, che consente di definire la propria funzione di filtraggio.

Ma alcuni potrebbero dire che è un po 'eccessivo, nella tua situazione ...
Un semplice foreach ciclo per andare attraverso la matrice e rimuovere l'elemento non si vuole dovrebbe essere sufficiente.

Qualcosa di simile, nel tuo caso, dovrebbe probabilmente fare il trucco:

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; 
    } 
} 
28

ne dite:

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

o per più valori:

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

Ciò impedirebbe anche la perdita chiave, che è un effetto collaterale di array_flip().

+1

non funzionerà se $ id è il primo elemento dell'array, meglio così: if (($ key = array_search ($ id, $ items))! == false) unset ($ items [$ key]); – Marek

+0

Buona cattura, lo aggiusterò. – zombat

+0

Grazie a @zombat, ha funzionato per me. – Pupil

5

vostre soluzioni funziona solo se si dispone di valori unici nella propria matrice

See:

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

Un modo migliore sarebbe impostata con array_search, in un ciclo, se necessario.

+0

hai ragione, ma in questo caso particolare sono abbastanza sicuro che i valori sono unici :) – Marek

33

Sto aggiungendo una seconda risposta. Ho scritto un breve script di benchmark per provare vari metodi qui.

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

Il terzo metodo, array_keys() con il parametro di ricerca opzionale specificato, sembra essere di gran lunga il metodo migliore. output di esempio:

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

giudicare da questo, la soluzione userei allora sarebbe:

$keysToRemove = array_keys($items,$id); 
foreach($keysToRemove as $k) { 
    unset($items[$k]); 
} 
+1

impressionante - grazie :) – Marek

+0

Penso che array_search sia un codice molto più leggibile rispetto all'utilizzo del metodo array_diff. Voto superiore – kendepelchin

+0

@ zombat Mi chiedo se l'ordine abbia qualcosa a che fare con i risultati. È possibile che shuffle metta il valore che stiamo cercando sia più vicino al fronte o alla fine. Diverso da quello ... +1 –

14

per rimuovere $rm_val da $arr

unset($arr[array_search($rm_val, $arr)]); 
3
function deleteValyeFromArray($array,$value) 
{ 
    foreach($array as $key=>$val) 
    { 
     if($val == $value) 
     { 
     unset($array[$key]); 
     } 
    } 
    return $array; 
} 
3

È possibile utilizzare array_splice funzione per questa operazione Rif: array_splice

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