Eliminazione dell'array PHP per valore (non chiave)


886

Ho un array PHP come segue:

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

Voglio eliminare l'elemento contenente il valore $del_val(ad esempio, $del_val=401), ma non conosco la sua chiave. Questo potrebbe aiutare: ogni valore può essere presente una sola volta .

Sto cercando la funzione più semplice per eseguire questa attività, per favore.


1
@Adam Strudwick Ma se hai molte eliminazioni su questo array, sarebbe meglio iterarlo una volta e rendere la sua chiave uguale a value?
dzona,


possibile duplicato di PHP Elimina un elemento da un array
Alex

Risposte:


1566

Utilizzando array_search()e unset, provare quanto segue:

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

array_search()restituisce la chiave dell'elemento che trova, che può essere usata per rimuovere quell'elemento dall'array originale usando unset(). Restituirà FALSEin caso di errore, tuttavia può restituire un valore false-y in caso di successo (la chiave potrebbe essere 0ad esempio), motivo per cui !==viene utilizzato l'operatore di confronto rigoroso .

L' if()istruzione verificherà se ha array_search()restituito un valore e eseguirà un'azione solo in caso affermativo .


14
Anche $ message = array_diff ($ message, array ($ del_val)) funzionerebbe anche? Sarebbe meglio nelle prestazioni?
Adam Strudwick,

9
@Adam Perché non provarlo? La mia sensazione è che array_diff()sarebbe più lento in quanto confronta due array, non semplicemente cercando in uno come array_search().
Bojangles,

22
Anche se questo è valido, dovresti evitare di assegnare valori in istruzioni del genere. Ti metterà nei guai.
adlawson,

17
E se $keyfosse 0?
evan

16
Se il valore che stai cercando ha una chiave 0o qualsiasi altro valore false, non disattiverà il valore e il tuo codice non funzionerà. Dovresti testare $key === false. (modifica- ce l'hai)
evan

674

Bene, eliminare un elemento dall'array è fondamentalmente solo impostare la differenza con un elemento.

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

Si generalizza bene, puoi rimuovere tutti gli elementi che vuoi allo stesso tempo, se vuoi.

Dichiarazione di non responsabilità: si noti che la mia soluzione produce una nuova copia dell'array mantenendo intatta quella vecchia in contrasto con la risposta accettata che muta. Scegli quello che ti serve.


32
funziona solo per oggetti che possono essere convertiti in una stringa
nischayn22

7
Mi sembra che stia ricevendo un "Errore di analisi" per averlo [$element]usato, array($element)invece. Nessun problema, ma volevo solo che chiunque avesse un problema simile sapesse che non erano soli
Angad,

8
Certo, ho ipotizzato che PHP 5.4 sia ora in maggioranza a eliminare la vecchia notazione. Grazie per l'osservazione.
Rok Kralj,

22
Vale la pena notare che per qualche ragione array_diffutilizza (string) $elem1 === (string) $elem2come condizione di uguaglianza, non $elem1 === $elem2come ci si potrebbe aspettare. La questione evidenziata da @ nischayn22 è una conseguenza di ciò. Se si desidera utilizzare qualcosa come funzione di utilità che funzionerà per array di elementi arbitrari (che potrebbero essere oggetti), la risposta di Bojangle potrebbe essere migliore per questo motivo.
Mark Amery,

4
Si noti inoltre che questo metodo esegue internamente un ordinamento per ogni argomento array_diff()e sposta quindi il runtime su O (n lg n) da O (n).
Ja͢ck,

115

Un modo interessante è usare array_keys():

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

Il array_keys() funzione accetta due parametri aggiuntivi per restituire solo le chiavi per un determinato valore e se è necessario un controllo rigoroso (ovvero usando === per il confronto).

Questo può anche rimuovere più elementi dell'array con lo stesso valore (ad es [1, 2, 3, 3, 4].).


3
@ blasteralfredΨ Una ricerca lineare è O (n); Non sono sicuro del motivo per cui sembri pensare che sia un problema.
Ja͢ck,

1
Sì, questo è efficace per la selezione di più voci / chiavi dell'array.
Oki Erie Rinaldi,

3
Questo è il migliore per array che potrebbero non contenere tutti i valori univoci.
Derokorian,

Il problema è che lascia l'indice delle chiavi in ​​ordine: [0] - a, [2] - b (il [1] non c'è più ma l'array lo manca ancora)
Rodniko il

3
@Rodniko nel qual caso avresti bisogno array_values()anche tu ; le chiavi rimanenti sono comunque nello stesso ordine, quindi tecnicamente non è "non ordinata"
Ja͢ck,

55

Se sai per certo che la tua matrice conterrà solo un elemento con quel valore, puoi farlo

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

Se, tuttavia, il valore può verificarsi più di una volta nell'array, è possibile farlo

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

Nota: la seconda opzione funziona solo per PHP5.3 + con le chiusure


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

11
Funziona solo quando l'array non contiene valori duplicati diversi da quelli che stai tentando di rimuovere.
jberculo,

2
@jberculo e talvolta esattamente ciò di cui hai bisogno, in alcuni casi mi salva facendo un array unico su di esso
DarkMukke

Forse, ma userei funzioni appositamente progettate per farlo, invece di essere solo un effetto collaterale fortunato di una funzione che è sostanzialmente usata e intesa per qualcos'altro. Renderebbe anche il tuo codice meno trasparente.
jberculo,

Il messaggio afferma che "ogni valore può essere presente una sola volta", dovrebbe funzionare. Sarebbe stato bello se il poster avesse usato i nomi delle variabili smae e avesse aggiunto una piccola spiegazione
Raatje,

2
apparentemente questo è il più veloce rispetto alla soluzione selezionata, ho fatto un piccolo benchmarking.
AMB,

28

Dai un'occhiata al seguente codice:

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

Tu puoi fare:

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

E questo ti darà questo array:

array('nice_item', 'another_liked_item')

1
Per gli array associativi devi usare array_diff_assoc ()
theCodeMachine

5
In che modo è diverso da questa risposta ?
random_user_name

26

Il modo migliore è array_splice

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

Reason for Best è disponibile all'indirizzo http://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/


4
Ciò non funzionerà su array associativi e array con lacune nelle loro chiavi, ad es [1, 2, 4 => 3].
Ja͢ck,

Non dispiace che funzionerà. Si prega di leggere l'articolo che ho fornito link
Airy

4
Non lo farà. Considera l'array del mio commento sopra; dopo aver usato il codice per rimuovere il valore 3, l'array sarà [1, 2, 3]; in altre parole, il valore non è stato rimosso. Per essere chiari, non sto dicendo che fallisce in tutti gli scenari, solo questo.
Ja͢ck,

1
array_splice è il metodo migliore, unset non regola gli indici dell'array dopo l'eliminazione
Raaghu

21

O semplicemente, in modo manuale:

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

Questo è il più sicuro perché hai il pieno controllo sul tuo array


1
Usando array_splice()invece di unset()riordinerai anche gli indici dell'array, il che potrebbe essere migliore in questo caso.
Daniele Orlando,

20

Con il seguente codice, i valori ripetitivi verranno rimossi dai $ messaggi.

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


3
Up-votato. Era già tra le altre risposte ma lo dici meglio mantenendolo semplice, come hai fatto. La risposta è semplicemente "array_diff"
ghbarratt

1
Sembra semplice ma cambia la complessità da O (n) a O (n lg n). Quindi, in realtà è più complesso;)
Krzysztof Przygoda il

20

Se hai PHP 5.3+, c'è il codice di una riga:

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

Sei sicuro? Quella chiusura non ha accesso $value, quindi in realtà deve essere inserita in una mini classe in modo da poter accedere $valueall'interno della chiusura ....
random_user_name

@cale_b, ho aggiornato l'esempio. Anche qui c'è il riferimento: php.net/manual/en/functions.anonymous.php
David Lin,

3
Potresti anche scrivere l'intero codice su una riga se chiami questo "codice di una riga"
Milano 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);

Produzione

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


2
non sono sicuro che questo sia più veloce poiché questa soluzione prevede più chiamate di funzione.
Julian Paolo Dayag,

13

tu puoi fare:

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

Spiegazione : Eliminare l'elemento che ha la chiave 401dopo aver capovolto l'array.


Devi stare molto attento se vuoi preservare lo stato. perché tutto il codice futuro dovrà avere valori anziché chiavi.
Saadlulu,

1
L'array di messaggi @saadlulu $ non verrà capovolto poiché array_flip () non influisce sull'array originale, quindi l'array risultante dopo aver applicato la riga precedente sarà lo stesso tranne che il risultato indesiderato verrà rimosso.
Qurashi,

2
non sono sicuro se questo è corretto, cosa succede se ci sono diversi elementi con il valore di 401?
Zippp

Ciò conserverà comunque le chiavi.
Szabolcs Páll

8

Per eliminare più valori, prova questo:

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

6

Preso in prestito la logica di underscore.JS _.reject e creato due funzioni (le persone preferiscono le funzioni !!)

array_reject_value: questa funzione sta semplicemente rifiutando il valore specificato (funziona anche per 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: questa funzione sta semplicemente rifiutando il metodo richiamabile (funziona per 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;
}

Quindi nel nostro esempio attuale possiamo usare le funzioni sopra come segue:

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

o anche meglio: (poiché questo ci dà una sintassi migliore da usare come quella array_filter )

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

Quanto sopra può essere usato per cose più complicate come diciamo che vorremmo rimuovere tutti i valori maggiori o uguali a 401, potremmo semplicemente fare questo:

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

1
Questo filtro reinventante non è? php.net/manual/en/function.array-filter.php
Richard Duerr,

Si Certamente. Come sto già dicendo al post "o anche meglio: (dato che questo ci dà una sintassi migliore da usare come quella array_filter)". A volte devi solo rifiutare la funzione come carattere di sottolineatura ed è proprio l'opposto del filtro (e devi ottenerlo con meno codice possibile). Questo è ciò che stanno facendo le funzioni. Questo è un modo semplice per rifiutare i valori.
John Skoumbourdis,

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

Prova questo, questo è il modo migliore e più veloce per rimuovere l'elemento in base al valore


5

La risposta di @Bojangles mi ha aiutato. Grazie.

Nel mio caso, l'array potrebbe essere associativo o meno, quindi ho aggiunto la seguente funzione

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
 }

}

Saluti


4

codice liner singolo (grazie a array_diff () ), utilizzare quanto segue:

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

4

La risposta accettata converte l'array in array associativo, quindi, se si desidera mantenerlo come array non associativo con la risposta accettata, potrebbe essere necessario utilizzare array_valuesanche.

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

Il riferimento è qui


4

Secondo il tuo requisito " ogni valore può essere lì solo per una volta " se sei solo interessato a mantenere valori univoci nel tuo array, allora array_unique()potrebbe essere quello che stai cercando.

Ingresso:

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

Risultato:

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

4

Se i valori che si desidera eliminare sono o possono essere in un array. Utilizzare la funzione array_diff . Sembra funzionare alla grande per cose come questa.

array_diff

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

1
In che modo è diverso da questa risposta ?
random_user_name

4

So che questo non è affatto efficiente ma è semplice, intuitivo e di facile lettura.
Quindi, se qualcuno è alla ricerca di una soluzione non così elegante che può essere estesa per lavorare con più valori o condizioni più specifiche .. ecco un semplice codice:

$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

Ottieni la chiave dell'array con array_search().


2
Come cancello il valore IF e solo se lo trovo con array_search?
Adam Strudwick,

3
$ k = array_search ($ ago, $ pagliaio, vero); if ($ k! == false) {unset ($ pagliaio [$ k]); }
evan

3

Se non conosci la sua chiave significa che non importa.

È possibile posizionare il valore come chiave, significa che troverà immediatamente il valore. Meglio che usare la ricerca in tutti gli elementi più e più volte.

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

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

Funziona solo con oggetti che possono essere convertiti in una stringa.
Emile Bergeron,

2

Un one-liner che utilizza l' oroperatore:

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

2

puoi fare riferimento a questo URL : per la funzione

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

Quindi l'output dovrebbe essere,

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


1

Penso che il modo più semplice sarebbe usare una funzione con un ciclo 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);

L'output sarà:

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

Con PHP 7.4 usando le funzioni freccia:

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

Per mantenerlo un array non associativo, avvolgetelo con array_values():

$messages = array_values(array_filter($messages, fn ($m) => $m != $del_val));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.