Wie bereits erwähnt, sind Pop und Del die effiziente Möglichkeit, ein Element eines bestimmten Index zu entfernen. Nur zur Vervollständigung (da dasselbe in Python auf viele Arten möglich ist):
Verwenden von Slices (dies führt nicht zum Entfernen des Elements aus der ursprünglichen Liste):
(Dies ist auch die am wenigsten effiziente Methode, wenn Sie mit Python-Listen arbeiten. Dies kann jedoch nützlich sein (aber nicht effizient, wie ich wiederhole), wenn Sie mit benutzerdefinierten Objekten arbeiten, die Pop nicht unterstützen, aber a definieren:) __getitem__
:
>>> a = [1, 2, 3, 4, 5, 6]
>>> index = 3 # Only positive index
>>> a = a[:index] + a[index+1 :]
# a is now [1, 2, 3, 5, 6]
Hinweis: Bitte beachten Sie, dass diese Methode die Liste wie pop
und nicht ändert del
. Stattdessen werden zwei Kopien von Listen erstellt (eine vom Anfang bis zum Index, jedoch ohne ( a[:index]
) und eine nach dem Index bis zum letzten Element ( a[index+1:]
)) und ein neues Listenobjekt erstellt, indem beide hinzugefügt werden. Dies wird dann der Listenvariablen ( a
) neu zugewiesen . Das alte Listenobjekt wird daher dereferenziert und somit Müll gesammelt (vorausgesetzt, das ursprüngliche Listenobjekt wird von keiner anderen Variablen als a referenziert).
Dies macht diese Methode sehr ineffizient und kann auch unerwünschte Nebenwirkungen hervorrufen (insbesondere wenn andere Variablen auf das ursprüngliche Listenobjekt verweisen, das unverändert bleibt).
Vielen Dank an @MarkDickinson für diesen Hinweis ...
Diese Antwort zum Stapelüberlauf erläutert das Konzept des Schneidens.
Beachten Sie auch, dass dies nur mit positiven Indizes funktioniert.
Bei der Verwendung mit Objekten muss die __getitem__
Methode definiert worden sein, und was noch wichtiger ist, die __add__
Methode muss definiert worden sein, um ein Objekt zurückzugeben, das Elemente aus beiden Operanden enthält.
Im Wesentlichen funktioniert dies mit jedem Objekt, dessen Klassendefinition wie folgt lautet:
class foo(object):
def __init__(self, items):
self.items = items
def __getitem__(self, index):
return foo(self.items[index])
def __add__(self, right):
return foo( self.items + right.items )
Dies funktioniert mit list
welchen Definitionen __getitem__
und __add__
Methoden.
Vergleich der drei Möglichkeiten hinsichtlich der Effizienz:
Angenommen, Folgendes ist vordefiniert:
a = range(10)
index = 3
Die del object[index]
Methode:
Mit Abstand die effizienteste Methode. Es funktioniert mit allen Objekten, die eine __del__
Methode definieren .
Die Demontage ist wie folgt:
Code:
def del_method():
global a
global index
del a[index]
Demontage:
10 0 LOAD_GLOBAL 0 (a)
3 LOAD_GLOBAL 1 (index)
6 DELETE_SUBSCR # This is the line that deletes the item
7 LOAD_CONST 0 (None)
10 RETURN_VALUE
None
pop
Methode:
Es ist weniger effizient als die del-Methode und wird verwendet, wenn Sie das gelöschte Element abrufen müssen.
Code:
def pop_method():
global a
global index
a.pop(index)
Demontage:
17 0 LOAD_GLOBAL 0 (a)
3 LOAD_ATTR 1 (pop)
6 LOAD_GLOBAL 2 (index)
9 CALL_FUNCTION 1
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
Die Slice-and-Add-Methode.
Am wenigsten effizient.
Code:
def slice_method():
global a
global index
a = a[:index] + a[index+1:]
Demontage:
24 0 LOAD_GLOBAL 0 (a)
3 LOAD_GLOBAL 1 (index)
6 SLICE+2
7 LOAD_GLOBAL 0 (a)
10 LOAD_GLOBAL 1 (index)
13 LOAD_CONST 1 (1)
16 BINARY_ADD
17 SLICE+1
18 BINARY_ADD
19 STORE_GLOBAL 0 (a)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
None
Hinweis: Ignorieren Sie bei allen drei Demontagen die letzten beiden Zeilen, die im Grunde genommen sind return None
. Auch die ersten beiden Zeilen laden die globalen Werte a
und index
.
O(n)
im Zeitbetrieb befindet.deque()
Bietet effiziente Operationen an beiden Enden, bietet jedoch keine O (1) Einfügungen / Suchvorgänge / Löschungen in der Mitte.