PHP-Array nach Wert löschen (nicht Schlüssel)

886

Ich habe ein PHP-Array wie folgt:

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

Ich möchte das Element löschen, das den Wert enthält $del_val(zum Beispiel $del_val=401), aber ich kenne seinen Schlüssel nicht. Dies könnte helfen: Jeder Wert kann nur einmal vorhanden sein .

Ich suche nach der einfachsten Funktion, um diese Aufgabe auszuführen.

Adam Strudwick
quelle
1
@Adam Strudwick Aber wenn Sie viele Löschungen in diesem Array haben, wäre es besser, es einmal zu wiederholen und seinen Schlüssel mit dem Wert gleichzusetzen?
Dzona
Gleiche Frage: stackoverflow.com/questions/1883421/…
Eric Lavoie
Mögliches Duplikat von PHP Löschen Sie ein Element aus einem Array
Alex

Antworten:

1566

Mit array_search()und unset, versuchen Sie Folgendes:

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

array_search()Gibt den Schlüssel des gefundenen Elements zurück, mit dem dieses Element mithilfe von aus dem ursprünglichen Array entfernt werden kann unset(). Es wird FALSEbei einem Fehler zurückgegeben, kann jedoch bei Erfolg einen Falsch-Y-Wert zurückgeben (Ihr Schlüssel kann 0beispielsweise sein), weshalb der strikte Vergleichsoperator !==verwendet wird.

Die if()Anweisung prüft, ob array_search()ein Wert zurückgegeben wurde, und führt nur dann eine Aktion aus, wenn dies der Fall ist.

Bojangles
quelle
14
Würde $ messages = array_diff ($ messages, array ($ del_val)) auch funktionieren? Wäre es besser in der Leistung?
Adam Strudwick
9
@ Adam Warum nicht testen? Mein Gefühl ist , dass array_diff()langsamer sein würde , wie es zwei Vergleichen Arrays, einfach nicht durch die Suche ein wie array_search().
Bojangles
22
Auch wenn dies gültig ist, sollten Sie vermeiden, in solchen Anweisungen Werte zuzuweisen. Es wird dich nur in Schwierigkeiten bringen.
Adlawson
17
Was passiert , wenn $keyist 0?
Evans
16
Wenn der 0gesuchte Wert einen Schlüssel oder einen anderen Falsey-Wert hat, wird der Wert nicht deaktiviert und Ihr Code funktioniert nicht. Sie sollten testen $key === false. (edit- du hast es)
evan
674

Nun, das Löschen eines Elements aus einem Array ist im Grunde nur ein Unterschied zwischen einem Element.

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

Es verallgemeinert sich gut, Sie können so viele Elemente gleichzeitig entfernen, wie Sie möchten, wenn Sie möchten.

Haftungsausschluss: Beachten Sie, dass meine Lösung eine neue Kopie des Arrays erstellt, während die alte intakt bleibt, im Gegensatz zu der akzeptierten Antwort, die mutiert. Wählen Sie die aus, die Sie benötigen.

Rok Kralj
quelle
32
Dies funktioniert nur für Objekte, die in einen String konvertiert werden können
nischayn22
7
Ich bekomme anscheinend einen "Analysefehler", weil [$element]ich gesagt habe , ich habe array($element)stattdessen verwendet. Kein Problem, aber ich wollte nur, dass jeder, der ein ähnliches Problem hatte, weiß, dass er nicht allein ist
Angad
8
Klar, ich habe angenommen, dass PHP 5.4 jetzt mehrheitlich die alte Notation fallen lässt. Danke für die Bemerkung.
Rok Kralj
22
Es ist erwähnenswert, dass aus irgendeinem Grund array_diffVerwendungen (string) $elem1 === (string) $elem2als Gleichheitsbedingung, nicht $elem1 === $elem2wie man erwarten könnte. Das von @ nischayn22 aufgezeigte Problem ist eine Folge davon. Wenn Sie möchten, dass etwas als Dienstprogrammfunktion für Arrays beliebiger Elemente (bei denen es sich möglicherweise um Objekte handelt) verwendet wird, ist die Antwort von Bojangle aus diesem Grund möglicherweise besser.
Mark Amery
4
Beachten Sie auch, dass diese Methode für jedes Argument intern eine Sortierung durchführt array_diff()und somit die Laufzeit von O (n) auf O (n lg n) anstößt.
Ja͢ck
115

Ein interessanter Weg ist die Verwendung von array_keys():

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

Die array_keys()Funktion benötigt zwei zusätzliche Parameter, um nur Schlüssel für einen bestimmten Wert zurückzugeben und um festzustellen, ob eine strikte Überprüfung erforderlich ist (dh === zum Vergleich verwenden).

Dies kann auch mehrere Array-Elemente mit demselben Wert entfernen (z [1, 2, 3, 3, 4]. B. ).

Jack
quelle
3
@ blasteralfredΨ Eine lineare Suche ist O (n); Ich bin mir nicht sicher, warum Sie denken, dass es ein Problem ist.
Ja͢ck
1
Ja, dies ist effektiv für die Auswahl mehrerer Array-Elemente / Schlüssel.
Oki Erie Rinaldi
3
Dies ist am besten für Arrays geeignet, die möglicherweise nicht alle eindeutigen Werte enthalten.
Derokorian
Das Problem ist, dass der Index der Schlüssel sortiert bleibt: [0] - a, [2] - b (die [1] ist weg, aber das Array vermisst sie immer noch)
Rodniko
3
@ Rodniko in welchem ​​Fall würden Sie auch brauchen array_values(); Die restlichen Schlüssel befinden sich jedoch immer noch in derselben Reihenfolge, so dass sie technisch gesehen nicht "unsortiert" sind
Ja͢ck
55

Wenn Sie sicher wissen, dass Ihr Array nur ein Element mit diesem Wert enthält, können Sie dies tun

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

Wenn Ihr Wert jedoch möglicherweise mehrmals in Ihrem Array vorkommt, können Sie dies tun

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

Hinweis: Die zweite Option funktioniert nur für PHP5.3 + mit Closures

Adlawson
quelle
41
$fields = array_flip($fields);
unset($fields['myvalue']);
$fields = array_flip($fields);
Rmannn
quelle
11
Dies funktioniert nur, wenn Ihr Array keine anderen doppelten Werte enthält als die, die Sie entfernen möchten.
Jberculo
2
@jberculo und manchmal genau das, was Sie brauchen, in einigen Fällen erspart es mir, ein einzigartiges Array zu erstellen
DarkMukke
Vielleicht, aber ich würde Funktionen verwenden, die speziell dafür entwickelt wurden, anstatt nur ein glücklicher Nebeneffekt einer Funktion zu sein, die im Grunde genommen für etwas anderes verwendet wird und bestimmt ist. Es würde auch Ihren Code weniger transparent machen.
Jberculo
Die Meldung lautet "Jeder Wert kann nur einmal vorhanden sein". Dies sollte funktionieren. Es wäre schön gewesen, wenn das Poster die Namen der smae-Variablen verwendet und eine kleine Erklärung hinzugefügt hätte
Raatje,
2
Anscheinend ist dies im Vergleich zur ausgewählten Lösung am schnellsten. Ich habe ein kleines Benchmarking durchgeführt.
AMB
28

Schauen Sie sich folgenden Code an:

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

Du kannst tun:

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

Und das bringt dir dieses Array:

array('nice_item', 'another_liked_item')
theCodeMachine
quelle
1
Für assoziative Arrays müssen Sie array_diff_assoc ()
theCodeMachine
5
Wie unterscheidet sich das von dieser Antwort ?
random_user_name
26

Der beste Weg ist array_splice

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

Grund für das Beste finden Sie hier unter http://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/

Luftig
quelle
4
Dies funktioniert nicht bei assoziativen Arrays und Arrays, deren Schlüssel Lücken aufweisen, z [1, 2, 4 => 3].
Ja͢ck
Nein, tut mir leid, das wird funktionieren. Bitte lesen Sie den Artikel, den ich Link zur Verfügung gestellt habe
Airy
4
Es wird nicht. Betrachten Sie das Array meines obigen Kommentars; Nachdem ich Ihren Code verwendet habe, um den Wert zu entfernen 3, wird das Array sein [1, 2, 3]; Mit anderen Worten, der Wert wurde nicht entfernt. Um es klar zu sagen, ich sage nicht, dass es in allen Szenarien fehlschlägt, nur in diesem.
Ja͢ck
1
array_splice ist die beste Methode, unset wird die Array-Indizes nach dem Löschen nicht anpassen
Raaghu
21

Oder einfach manuell:

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

Dies ist die sicherste davon, da Sie die volle Kontrolle über Ihr Array haben

Victor Priceputu
quelle
1
Wenn Sie array_splice()anstelle von verwenden, unset()werden auch die Array-Indizes neu angeordnet, was in diesem Fall besser sein könnte.
Daniele Orlando
20

Mit dem folgenden Code werden die sich wiederholenden Werte aus den $ -Nachrichten entfernt.

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

Syed Abidur Rahman
quelle
3
Up-Voted. Es war bereits unter den anderen Antworten, aber Sie sagen es am besten, indem Sie es einfach halten, wie Sie es getan haben. Die Antwort ist einfach "array_diff"
ghbarratt
1
Sieht einfach aus, ändert aber die Komplexität von O (n) zu O (n lg n). Also ist es in der Tat komplexer;)
Krzysztof Przygoda
20

Wenn Sie PHP haben 5.3+, gibt es den einzeiligen Code:

$array = array_filter($array, function ($i) use ($value) { return $i !== $value; }); 
David Lin
quelle
Bist du sicher? Dieser Abschluss hat keinen Zugriff auf $value, also muss er wirklich in eine $value
Miniklasse eingeordnet werden,
@cale_b, ich habe das Beispiel aktualisiert. Auch hier ist die ref: php.net/manual/en/functions.anonymous.php
David Lin
3
Sie können auch Ihre gesamte Codebasis in eine Zeile schreiben, wenn Sie diesen "Einzeilencode" nennen
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);

Ausgabe

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

tttony
quelle
2
Ich bin mir nicht sicher, ob dies schneller ist, da diese Lösung mehrere Funktionsaufrufe umfasst.
Julian Paolo Dayag
13

du kannst tun:

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

Erläuterung : Löschen Sie das Element mit dem Schlüssel 401nach dem Umdrehen des Arrays.

Qurashi
quelle
Sie müssen sehr vorsichtig sein, wenn Sie den Staat erhalten wollen. weil jeder zukünftige Code Werte anstelle von Schlüsseln haben muss.
Saadlulu
1
Das Array @saadlulu $ messages wird nicht gespiegelt, da array_flip () das ursprüngliche Array nicht beeinflusst. Das resultierende Array nach dem Anwenden der vorherigen Zeile ist also dasselbe, außer dass das unerwünschte Ergebnis entfernt wird.
Qurashi
2
Sie sind sich nicht sicher, ob dies korrekt ist. Was ist, wenn mehrere Elemente mit dem Wert von vorhanden sind 401?
Zippp
Dadurch bleiben die Schlüssel erhalten.
Szabolcs Páll
8

Um mehrere Werte zu löschen, versuchen Sie Folgendes:

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

Leihte sich die Logik von Unterstrich.JS _.reject und erstellte zwei Funktionen (Leute bevorzugen Funktionen !!)

array_reject_value: Diese Funktion lehnt einfach den angegebenen Wert ab (funktioniert auch für 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: Diese Funktion lehnt einfach die aufrufbare Methode ab (funktioniert für 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;
}

In unserem aktuellen Beispiel können wir die obigen Funktionen wie folgt verwenden:

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

oder noch besser: (da dies uns eine bessere Syntax gibt, die wir wie die von array_filter verwenden können )

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

Das Obige kann für kompliziertere Dinge verwendet werden, wie zum Beispiel, wenn wir alle Werte entfernen möchten, die größer oder gleich 401 sind. Wir könnten dies einfach tun:

$messages = [312, 401, 1599, 3, 6];
$greaterOrEqualThan = 401;
$messages = array_reject($messages, function ($value) use $greaterOrEqualThan {
    return $value >= $greaterOrEqualThan;
});
John Skoumbourdis
quelle
1
Erfindet dieser Filter nicht neu? php.net/manual/en/function.array-filter.php
Richard Duerr
Ja in der Tat. Wie ich bereits im Beitrag sage "oder noch besser: (da dies uns eine bessere Syntax gibt, die wir wie die von array_filter verwenden können)". Manchmal muss die Funktion wirklich nur als Unterstrich abgelehnt werden, und sie ist genau das Gegenteil des Filters (und Sie müssen sie mit so wenig Code wie möglich erhalten). Dies ist, was die Funktionen tun. Dies ist eine einfache Möglichkeit, Werte abzulehnen.
John Skoumbourdis
6
$array = array("apple", "banana",'mango');
$array = array_filter($array, function($v) { return $v != "apple"; });

Versuchen Sie Folgendes: Dies ist der beste und schnellste Weg, um Elemente nach Wert zu entfernen

Paras Raiyani
quelle
5

@ Bojangles Antwort hat mir geholfen. Vielen Dank.

In meinem Fall kann das Array assoziativ sein oder nicht, daher habe ich die folgende Funktion hinzugefügt

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
 }

}

Grüße

Angeltcho
quelle
4

Die akzeptierte Antwort konvertiert das Array in ein assoziatives Array. Wenn Sie es also als nicht assoziatives Array mit der akzeptierten Antwort beibehalten möchten, müssen Sie es möglicherweise auch verwenden array_values.

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

Die Referenz ist hier

SaidbakR
quelle
4

Gemäß Ihrer Anforderung " Jeder Wert kann nur einmal vorhanden sein ", wenn Sie nur daran interessiert sind, eindeutige Werte in Ihrem Array beizubehalten, ist dies array_unique()möglicherweise das, wonach Sie suchen.

Eingang:

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

Ergebnis:

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

Wenn sich Werte, die Sie löschen möchten, in einem Array befinden oder befinden können. Verwenden Sie die Funktion array_diff . Scheint für solche Dinge großartig zu funktionieren.

array_diff

$arrayWithValuesRemoved = array_diff($arrayOfData, $arrayOfValuesToRemove);
user1518699
quelle
1
Wie unterscheidet sich das von dieser Antwort ?
random_user_name
4

Ich weiß, dass dies überhaupt nicht effizient ist, aber einfach, intuitiv und leicht zu lesen ist.
Wenn also jemand nach einer nicht so ausgefallenen Lösung sucht, die erweitert werden kann, um mit mehr Werten oder spezifischeren Bedingungen zu arbeiten, dann ist hier ein einfacher Code:

$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
d.raev
quelle
4

Holen Sie sich den Array-Schlüssel mit array_search().

evan
quelle
2
Wie lösche ich den Wert IF und nur, wenn ich ihn mit array_search finde?
Adam Strudwick
3
$ k = array_search ($ Nadel, $ Heuhaufen, wahr); if ($ k! == false) {unset ($ haystack [$ k]); }
Evans
3

Wenn Sie den Schlüssel nicht kennen, bedeutet dies, dass es keine Rolle spielt.

Sie können den Wert als Schlüssel eingeben. Dies bedeutet, dass der Wert sofort gefunden wird. Besser als die Suche in allen Elementen immer und immer wieder zu verwenden.

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

unset($messages[3]); // no search needed
Ismael
quelle
Funktioniert nur für Objekte, die in eine Zeichenfolge konvertiert werden können.
Emile Bergeron
2

Ein Einzeiler mit dem orOperator:

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

Sie können auf diese URL verweisen : für die Funktion

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

Dann sollte die Ausgabe sein,

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

Ich denke, der einfachste Weg wäre, eine Funktion mit einer foreach-Schleife zu verwenden:

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

Ausgabe wird sein:

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)
}
algo
quelle
1

Mit PHP 7.4 mit Pfeilfunktionen:

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

Um es als nicht assoziatives Array beizubehalten, umschließen Sie es mit array_values():

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