Seite 1 von 1
Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 15:28
von Modibo
Hallo,
ich habe eine Liste der Form:
Code: Alles auswählen
l=[[["t1", "t2", "t3", "t4", "t5", "t6","w1", "w2", "w3", "w4", "w5", "w6","z1", "z2", "z3", "z4", "z5", "z6"],[],[]], ..., [["t1", "t2", "t3", "t4", "t5", "t6", "w1", "w2", "w3", "w4", "w5", "w6", z1", "z2", "z3", "z4", "z5", "z6"],[],[]]]
und möchte aus der ersten "Unterliste" die Elemente einer zweiten Liste löschen
Code: Alles auswählen
for i in range(len(zweite_liste)):
l[0][0].remove(zweite_liste[i])
Aber irgendwie ist da ein Fehler drin, den ich nicht finde, weil der Code mir aus
allen Unterlisten die Elemente der zweiten Liste löscht.
Wo ist der Fehler??
Gruß Modibo
Re: Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 15:45
von snafu
In Python benötigt man keinen mitgeführten Indexwert zum Iterieren, sondern kann direkt über die Elemente gehen. Ungetestet:
Code: Alles auswählen
for element in l[0][0]:
if element in andere_liste:
l[0][0].remove(element)
Oder quasi für Fortgeschrittene:
Code: Alles auswählen
elems = [elem for elem in l[0][0] if elem not in andere_liste]
l[0][0] = elems
Natürlich mit dem Unterschied, dass im zweiten Fall eine neue Liste angelegt wird, während du im ersten Fall die bestehende Liste einfach nur veränderst. Die zweite Variante sollte dafür eine deutlich bessere Laufzeit haben.
Re: Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 15:50
von Modibo
Ah, ok.
Ich probier's mal aus.
Danke für die schnelle Antwort.
Re: Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 16:02
von snafu
Übrigens, falls du viel mit Mengen arbeiten musst und du Kontrolle über die Daten bei ihrer Erzeugung hast, dann würde ich zum eingebauten Datentyp `set()` raten. Für dein Vorhaben hätte dann ein Aufruf von `l[0][0].
difference_update(andere_liste)` gereicht, um die "unerwünschten" Elemente sozusagen inplace aus der Unterliste (bzw. -menge) zu entfernen.
Re: Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 16:05
von Modibo
Ne, der output ist genau der selbe, wie bei meiner Version (Element wird aus allen Unterlisten gelöscht)
Ich poste mal das ganze Programm, vllt mach ich wo anders den Fehler.
Bin ja eh noch am Anfang:
Code: Alles auswählen
class Listen():
def __init__(self):
self.db = []
self.nlist = ["t1", "t2", "t3", "t4", "t5", "t6",
"w1", "w2", "w3", "w4", "w5", "w6",
"z1", "z2", "z3", "z4", "z5", "z6"]
self.mlist = []
self.plist = []
self.flist = []
print "Wie viel Spieler spielen mit?"
self.p_anzahl = int(input())
while self.p_anzahl-1 >= 0:
self.db+=[[self.nlist, self.mlist, self.plist]]
self.p_anzahl-=1
self.print_db() # zeigt die gesamte Datenbank geordnet an
self.eigene_Karten()
print self.db
def eigene_Karten(self):
print "An welcher Position (beginnend vom Spieler der anfängt) sitzt du?"
self.position = 1 #int(input())
print "Welche Karten hast du auf der Hand?"
self.precards = ["t1"] #input()
for element in self.db[self.position-1][0]:
if element in self.precards:
self.db[self.position-1][0].remove(element)
def print_db(self):
for i in range(len(self.db)):
print self.db[i]
print "\n"
def main():
print "Hallo World!"
return 0
if __name__ == '__main__':
main()
lst = Listen()
Re: Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 16:08
von BlackJack
@Modibo: Das Element wird aus der *einen* Liste entfernt, die Du überhaupt nur hast. Wenn Du immer wieder die *selbe* Liste verwendest, dann sieht man natürlich auch die Änderung daran über jeden Weg, über den man diese eine Liste erreichen kann.
Re: Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 16:21
von snafu
Dein Denkfehler ist sehr wahrscheinlich in dieser Zeile:
Da wird nicht auf magische Weise jedes Mal eine neue `nlist` erstellt, sondern immer der Verweis auf die selbe Liste genommen. Wenn du so willst, erstellst du zwar jedes Mal eine neue Liste mit 3 Verweisen. Jeder von diesen 3 Verweisen zeigt aber auf das jeweils selbe Objekt. Also auf das, was z.B. über `self.nlist` erreicht wird. Und wenn du die "Ursprungsquelle" veränderst, dann zeigt eben auch jeder der "Verweisgruppen" auf dieses veränderte Ziel.
Im Übrigen unterscheidet sich dein eingangs gezeigter Code von den Auswirkungen her dabei nicht von meinem. Hatte da gar nicht drauf geachtet, sondern erstmal nur das unpythonische daran gesehen.
Nochmal zur Demonstration des Verhaltens:
Code: Alles auswählen
>>> r = range(3)
>>> l = [r, r]
>>> l[0] is l[1]
True
>>> l[0]
[0, 1, 2]
>>> l[1]
[0, 1, 2]
>>> l[0].append(3)
>>> l[0]
[0, 1, 2, 3]
>>> l[1]
[0, 1, 2, 3]
Re: Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 16:34
von Modibo
snafu hat geschrieben:Dein Denkfehler ist sehr wahrscheinlich in dieser Zeile:
Da wird nicht auf magische Weise jedes Mal eine neue `nlist` erstellt, sondern immer der Verweis auf die selbe Liste genommen. Wenn du so willst, erstellst du zwar jedes Mal eine neue Liste mit 3 Verweisen. Jeder von diesen 3 Verweisen zeigt aber auf das jeweils selbe Objekt. Also auf das, was z.B. über `self.nlist` erreicht wird. Und wenn du die "Ursprungsquelle" veränderst, dann zeigt eben auch jeder der "Verweisgruppen" auf dieses veränderte Ziel.
Ah ja! Jetzt versteh ich.
Super, vielen vielen Dank!!!
Den Typ set() werde ich mir dann auch mal anschauen.
Re: Listenelement entfernen
Verfasst: Samstag 28. Januar 2012, 16:49
von snafu
Modibo hat geschrieben:Den Typ set() werde ich mir dann auch mal anschauen.
Jau. Für deinen Code wäre es dann halt entsprechend:
Deutlich weniger Code und IMHO auch gut nachvollziehbar beim Lesen. Denk nur dran, dass Listen das leider nicht können, sondern wirklich nur `set()`s.