Listenelement entfernen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

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
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

Ah, ok.
Ich probier's mal aus.

Danke für die schnelle Antwort.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ü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.
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

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()
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.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dein Denkfehler ist sehr wahrscheinlich in dieser Zeile:

Code: Alles auswählen

self.db+=[[self.nlist, self.mlist, self.plist]]
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. :oops:

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]
Modibo
User
Beiträge: 22
Registriert: Samstag 19. Februar 2011, 16:06

snafu hat geschrieben:Dein Denkfehler ist sehr wahrscheinlich in dieser Zeile:

Code: Alles auswählen

self.db+=[[self.nlist, self.mlist, self.plist]]
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.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Modibo hat geschrieben:Den Typ set() werde ich mir dann auch mal anschauen.
Jau. Für deinen Code wäre es dann halt entsprechend:

Code: Alles auswählen

self.db[self.position-1][0] -= self.precards
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.
Antworten