Entfernen Sie mehrere Elemente aus einer Python-Liste in nur einer Anweisung

107

In Python weiß ich, wie man Elemente aus einer Liste entfernt.

item_list = ['item', 5, 'foo', 3.14, True]
item_list.remove('item')
item_list.remove(5)

Dieser obige Code entfernt die Werte 5 und 'item' aus item_list. Aber wenn es viel zu entfernen gibt, muss ich viele Zeilen schreiben

item_list.remove("something_to_remove")

Wenn ich den Index dessen kenne, was ich entferne, verwende ich:

del item_list[x]

Dabei ist x der Index des Elements, das ich entfernen möchte.

Wenn ich den Index aller Zahlen kenne, die ich entfernen möchte, verwende ich eine Art Schleife für deldie Elemente an den Indizes.

Aber was ist, wenn ich die Indizes der Elemente, die ich entfernen möchte, nicht kenne?

Ich habe es versucht item_list.remove('item', 'foo'), aber ich habe eine Fehlermeldung erhalten, dass removenur ein Argument erforderlich ist.

Gibt es eine Möglichkeit, mehrere Elemente in einer einzigen Anweisung aus einer Liste zu entfernen?

PS Ich habe verwendet delund remove. Kann jemand den Unterschied zwischen diesen beiden erklären oder sind sie gleich?

Vielen Dank

RandomCoder
quelle
1
So beantworten Sie Ihre zweite Frage: delLöscht ein Element anhand seines Index. Die removeFunktion einer Liste findet den Index eines Elements und ruft deldiesen Index dann auf.
Aaron Christiansen
Mögliches Duplikat des Löschens mehrerer Elemente aus einer Liste
IMLD

Antworten:

159

In Python ist das Erstellen eines neuen Objekts häufig besser als das Ändern eines vorhandenen Objekts:

item_list = ['item', 5, 'foo', 3.14, True]
item_list = [e for e in item_list if e not in ('item', 5)]

Welches ist gleichbedeutend mit:

item_list = ['item', 5, 'foo', 3.14, True]
new_list = []
for e in item_list:
    if e not in ('item', 5):
        new_list.append(e)
item_list = new_list

Bei einer großen Liste herausgefilterter Werte (hier ('item', 5)ein kleiner Satz von Elementen) kann die Verwendung von a setzu einer Leistungsverbesserung führen, da die inOperation in O (1) ausgeführt wird:

item_list = [e for e in item_list if e not in {'item', 5}]

Beachten Sie, dass, wie in den Kommentaren erläutert und hier vorgeschlagen , Folgendes noch mehr Zeit sparen kann, wodurch vermieden wird, dass der Satz in jeder Schleife erstellt wird:

unwanted = {'item', 5}
item_list = [e for e in item_list if e not in unwanted]

Ein Bloom-Filter ist auch eine gute Lösung, wenn der Speicher nicht billig ist.

Aluriak
quelle
Ich mag die erste Antwort. Ich mache keine neue Liste, was gut ist. Vielen Dank!
RandomCoder
Ist das Set in Python 2 optimiert oder ist es nur in Python 3 optimiert? Damit meine ich, wird die Menge nur einmal erstellt, wenn der Bytecode generiert wird?
Har
Set ist, per Definition , für eine optimierte inBedienung. In diesen Benchmarks finden Sie Vergleiche der vier primitiven Datenstrukturen. Ja, die Menge wird in jeder Schleife erstellt, wie hier vorgeschlagen. Wenn Sie die Menge daher in einer dedizierten Variablen speichern, die im Generatorausdruck verwendet wird, können Sie Zeit sparen.
Aluriak
@RandomCoder Sie erstellen tatsächlich eine neue Liste, Sie verwenden nur einen Namen. Sie können dies überprüfen, indem Sie id(item_list)vorher und nachher vergleichen item_list = [e for e in item_list if e not in ('item', 5)]. Überprüfen Sie meine Antwort, um zu sehen, wie Sie eine Liste an Ort und Stelle ändern können.
Darkonaut
20
item_list = ['item', 5, 'foo', 3.14, True]
list_to_remove=['item', 5, 'foo']

Die endgültige Liste nach dem Entfernen sollte wie folgt lauten

final_list=[3.14, True]

Einzeiliger Code

final_list= list(set(item_list).difference(set(list_to_remove)))

Ausgabe wäre wie folgt

final_list=[3.14, True]
Aakash Goel
quelle
13
Nein, es mischt die Elemente in der Liste. Nur verwenden, wenn die Reihenfolge der Artikel keine Rolle spielt, was häufig der Fall ist.
Aasfresser
5
Dadurch werden auch Duplikate aus der Liste entfernt. Nicht, dass es für die Beispielliste
wichtig
1
Diese Antwort ist falsch und kann schwerwiegende Fehler verursachen. Warum wird sie positiv bewertet?
Omerfarukdogan
1
Duplikate werden entfernt! Die Antwort kann schwerwiegende Fehler verursachen, bitte nicht verwenden.
user2698178
2

Ich weiß nicht, warum jeder vergessen hat, die erstaunlichen Fähigkeiten von sets in Python zu erwähnen . Sie können Ihre Liste einfach in einen Satz umwandeln und dann alles, was Sie entfernen möchten, in einem einfachen Ausdruck wie folgt entfernen:

>>> item_list = ['item', 5, 'foo', 3.14, True]
>>> item_list = set(item_list) - {'item', 5}
>>> item_list
{True, 3.14, 'foo'}
>>> # you can cast it again in a list-from like so
>>> item_list = list(item_list)
>>> item_list
[True, 3.14, 'foo']
Anwarvic
quelle
6
Behält jedoch nicht die Reihenfolge der Objekte bei.
Astrid
Außerdem werden möglicherweise in der Liste vorhandene Duplikate entfernt.
kyriakosSt
1

Ich poste meine Antwort von hier aus neu , weil ich gesehen habe, dass sie auch hier passt. Es ermöglicht das Entfernen mehrerer Werte oder nur das Duplizieren dieser Werte und gibt entweder eine neue Liste zurück oder ändert die angegebene Liste.


def removed(items, original_list, only_duplicates=False, inplace=False):
    """By default removes given items from original_list and returns
    a new list. Optionally only removes duplicates of `items` or modifies
    given list in place.
    """
    if not hasattr(items, '__iter__') or isinstance(items, str):
        items = [items]

    if only_duplicates:
        result = []
        for item in original_list:
            if item not in items or item not in result:
                result.append(item)
    else:
        result = [item for item in original_list if item not in items]

    if inplace:
        original_list[:] = result
    else:
        return result

Docstring-Erweiterung:

"""
Examples:
---------

    >>>li1 = [1, 2, 3, 4, 4, 5, 5]
    >>>removed(4, li1)
       [1, 2, 3, 5, 5]
    >>>removed((4,5), li1)
       [1, 2, 3]
    >>>removed((4,5), li1, only_duplicates=True)
       [1, 2, 3, 4, 5]

    # remove all duplicates by passing original_list also to `items`.:
    >>>removed(li1, li1, only_duplicates=True)
      [1, 2, 3, 4, 5]

    # inplace:
    >>>removed((4,5), li1, only_duplicates=True, inplace=True)
    >>>li1
        [1, 2, 3, 4, 5]

    >>>li2 =['abc', 'def', 'def', 'ghi', 'ghi']
    >>>removed(('def', 'ghi'), li2, only_duplicates=True, inplace=True)
    >>>li2
        ['abc', 'def', 'ghi']
"""

Sie sollten sich darüber im Klaren sein, was Sie wirklich tun möchten, eine vorhandene Liste ändern oder eine neue Liste mit den fehlenden spezifischen Elementen erstellen. Es ist wichtig, diese Unterscheidung zu treffen, wenn Sie einen zweiten Verweis auf die vorhandene Liste haben. Wenn Sie zum Beispiel haben ...

li1 = [1, 2, 3, 4, 4, 5, 5]
li2 = li1
# then rebind li1 to the new list without the value 4
li1 = removed(4, li1)
# you end up with two separate lists where li2 is still pointing to the 
# original
li2
# [1, 2, 3, 4, 4, 5, 5]
li1
# [1, 2, 3, 5, 5]

Dies kann das gewünschte Verhalten sein oder auch nicht.

Darkonaut
quelle
1

Sie können die Filterfalse- Funktion aus dem itertools- Modul verwenden

Beispiel

import random
from itertools import filterfalse

random.seed(42)

data = [random.randrange(5) for _ in range(10)]
clean = [*filterfalse(lambda i: i == 0, data)]
print(f"Remove 0s\n{data=}\n{clean=}\n")


clean = [*filterfalse(lambda i: i in (0, 1), data)]
print(f"Remove 0s and 1s\n{data=}\n{clean=}")

Ausgabe:

Remove 0s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 1, 1, 1, 4, 4]

Remove 0s and 1s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 4, 4]
Vlad Bezden
quelle
0

Aber was ist, wenn ich die Indizes der Elemente, die ich entfernen möchte, nicht kenne?

Ich verstehe nicht genau, warum Sie .remove nicht mögen, aber um den ersten Index zu erhalten, der einem Wert entspricht, verwenden Sie .index (Wert):

ind=item_list.index('item')

Entfernen Sie dann den entsprechenden Wert:

del item_list.pop[ind]

.index (Wert) erhält das erste Auftreten von Wert und .remove (Wert) entfernt das erste Auftreten von Wert

aless80
quelle
Verwenden Sie del item_list[ind]statt, popwenn Sie den Ergebniswert nicht benötigen.
Kojiro
-1

Sie können dies verwenden -

Angenommen, wir haben eine Liste, l = [1,2,3,4,5]

Wir möchten die letzten beiden Elemente in einer einzigen Anweisung löschen

del l[3:]

Wir haben ausgegeben:

l = [1,2,3]

Halte es einfach

Krishna Singhal
quelle