Wie kann ich ein Sammlungselement nach dem Abrufen deaktivieren (entfernen)?

78

Ich habe eine Sammlung, die ich iterieren und ändern möchte, während ich einige ihrer Elemente abrufe. Aber ich konnte keinen Weg oder keine Methode finden, um dieses abgerufene Element zu entfernen.

$selected = []; 
foreach ($collection as $key => $value) {
      if ($collection->selected == true) {
          $selected[] = $value;
          unset($value);
      }
}

Dies ist nur eine Darstellung meiner Demonstrationsfrage.

Nach dem Rat von @Ohgodwhy der Funktion compare () habe ich sie erneut überprüft und festgestellt, dass ich die Funktion tatsächlich falsch verstanden habe. Es war genau so, wie ich es gesucht hatte.

Für eine funktionierende Lösung habe ich also $collection->forget($key)die if-Anweisung hinzugefügt .

Unten ist die funktionierende Lösung meines Problems unter Verwendung der Lösung von @ Ohgodwhy:

$selected = []; 
foreach ($collection as $key => $value) {
      if ($collection->selected == true) {
          $selected[] = $value;
          $collection->forget($key);
      }
}

(Dies ist nur eine Demonstration)

Skeletor
quelle
1
Ich würde vorschlagen, Ihre Elemente nicht in einem Array zu speichern, sondern eine neue Sammlung zu erstellen und die Elemente durch Push hinzuzufügen.
Amarnasan
@Amarnasan Wie würde das gehen? Ich brauche es jetzt nicht, aber ich denke, ich kann es in Zukunft brauchen
Charlie
Schauen Sie hier: stackoverflow.com/a/58769554/655224 . Ihr ifZustand $collection->selected == truemacht keinen Sinn. Warum die Eigenschaft selecteddes collectionObjekts überprüfen, nicht die des value? Wenn sich die Eigenschaft tatsächlich innerhalb befindet, collectionüberprüfen Sie sie einmal außerhalb Ihrer Schleife.
Algorithmus

Antworten:

124

Sie würden verwenden wollen ->forget()

$collection->forget($key);

Link zur Dokumentation zur Vergessensmethode

Oh Gott warum
quelle
1
Ja eigentlich habe ich vergessen () falsch verstanden. Ich dachte, $ key Parameter entfernt alle angegebenen Schlüssel. Jetzt konnte ich es direkt in der Schleife mit einer if-Anweisung verwenden.
Skeletor
18
forget()ist cool im Vergleich zu delete()oder remove(), aber zur Hölle, ich musste hierher kommen, um herauszufinden, wie man einen Gegenstand entfernt :)
Attila Fulop
Was ist, wenn Sie das gesamte Objekt löschen möchten?
Chaudhry Waqas
5
@Adamnick Mit müssten forgetSie indexdas Objekt im Array kennen. Was Sie wollen, ist wahrscheinlichfilter()
Ohgodwhy
Für alle, die sich das jetzt ansehen
Bryce Meyer
25

Oder Sie können reject Methode verwenden

$newColection = $collection->reject(function($element) {
    return $item->selected != true;
});

oder pull Methode

$selected = []; 
foreach ($collection as $key => $item) {
      if ($item->selected == true) {
          $selected[] = $collection->pull($key);
      }
}
huuuk
quelle
1
Aber die Ablehnungslösung würde die Elemente nicht aus der ursprünglichen Sammlung entfernen, oder?
Amarnasan
Ja, es hält die ursprüngliche Sammlung intakt
Huuuk
1
Dann wäre die perfekte Lösung für die Frage die zweite.
Amarnasan
$collection = $collection->reject(...)überschreibt die ursprüngliche Sammlung mit der neuen Sammlung. Und $collection->pull(...)ist die beste Lösung, denke ich. Die Themenüberschrift enthält ...after fetching it.... Das pullmacht es.
Algorithmus
13

Laravel Collectionimplementiert die PHP- ArrayAccessSchnittstelle (weshalb die Verwendung überhaupt foreachmöglich ist).

Wenn Sie den Schlüssel bereits haben, können Sie einfach PHP verwenden unset.

Ich bevorzuge dies, weil es die vorhandene Sammlung deutlich verändert und leicht zu merken ist.

foreach ($collection as $key => $value) {
    unset($collection[$key]);
}
andrewtweber
quelle
1

Ich bin nicht in Ordnung mit Lösungen, die über eine Sammlung iterieren und innerhalb der Schleife den Inhalt selbst dieser Sammlung manipulieren. Dies kann zu unerwartetem Verhalten führen.

Siehe auch hier: https://stackoverflow.com/a/2304578/655224 und in einem Kommentar den angegebenen Link http://php.net/manual/en/control-structures.foreach.php#88578

Wenn Sie also foreachif verwenden, scheint dies meiner Meinung nach in Ordnung zu sein, besteht die viel besser lesbare und einfachere Lösung darin, Ihre Sammlung nach einer neuen zu filtern.

/**
 * Filter all `selected` items
 *
 * @link https://laravel.com/docs/7.x/collections#method-filter
 */
$selected = $collection->filter(function($value, $key) {
    return $value->selected;
})->toArray();
Algorithmus
quelle
0

Wenn Sie den Schlüssel kennen, den Sie deaktiviert haben, setzen Sie ihn direkt durch Komma getrennt

unset($attr['placeholder'], $attr['autocomplete']);
Kaushik Shrimali
quelle
Ich habe einen Sonderfall erhalten, bei dem ich ein Artikelauflistungssystem erhalten habe, bei dem eine neue Eigenschaft in der neuesten Eigenschaftensammlung und auch in einer nicht bewerteten Sammlung zurückgegeben wird, die ich alle auf einer Seite zeige. Ich möchte, dass die Elemente, die bereits in der ersten Liste enthalten sind, aus der zweiten Liste entfernt werden. Wie mache ich das? Denken Sie daran, dass Sie dem Index nicht sagen können, in dem das Element angezeigt wird. Kann ich so etwas tun $collection->forget($item->id) ?
Softwareentwickler