Doppelte finden

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
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

huhu!


Ich habe zwei Arrays. Die Elemente, die in beiden Arrays vorkommen, sollen von einem entfernt werden.
Das habe ich so gelöst:

Code: Alles auswählen

x=[1,2,3]
y=[9,8,7,1]

for c in range(len(y)):
    if y[c] in x:
        del y[c]
Das funktioniert auch.
Doch wenn ich es in mein Hauptprogramm einbinde, kommt die Meldung
if umgebung[c] in kombi:
IndexError: list index out of range


"umgebung" entspricht "y" und
"kombi" sieht wie "x" aus.

Das alles ist in mehreren ineinander geschachtelten Schleifen eingebaut, sodass ich nicht dahinter komme, wo der Fehler liegt.
Als isoliertes Programm funktioniert es ja...
Ich denke, dass dadruch, dass ein Element von y entfernt wird, die Schleife ja einmal zu lange durchläuft, da sie ja mit len(y) gestartet wurde und da y noch ein Element länger war.

Ich habe alles mögliche probiert, um den Fehler zu finden... Ich habe Ausgaben an allen möglichen Stellen eingebaut, um die jeweiligen Zwischenergebnisse zu überprüfen... Alles läuft nach Plan bis zu dieser Stelle...
Wenn ich

Code: Alles auswählen

x=[1,2,3]
y=[9,8,7,1]

for c in range(len(y)):
    if y[c] in x:
        1+1
        #del y[c]
durchlaufen lasse, gibt es keinen Fehler im Hauptprogramm. Es muss also an einem Überlauf durch das Entfernen liegen.

Hat jemand irgendwelche Ideen?
Vielleicht eine Alternative, wie man aus einem Array alle Elemente entfernen kann, die in einem anderen Array enthalten sind?
Vielleicht gibt es mit einer Alternativlösung kein Problem mit dem Überlauf...

Mir ist noch eine (wenn auch sehr unelegante) Möglichkeit eingefallen, wie ich das Probelm umgehen könnte.
Dazu fehlt mir aber ein Befehl.
a.remove(b) entfernt ja nur das erste b und nicht alle b.
Ich brauche aber einen Befehl, der alle b aus a entfernt.
Wie heißt der?


Gruß
Paul
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du darfst nichts aus Listen löschen durch die du gerade iterierst.

Die einfachste Lösung: Einfach eine neue Liste erstellen. Schau dir dazu mal List Comprehensions (oder alternativ die filter-Funktion) und Mengen an.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Dein erstes Codebeispiel funktioniert nur zufaellig, da das zu loeschende Element (die 1) in y als letztes steht. Das Problem ist, das du die Liste wahrend der Iteration veranderst: Du machst die Liste kuerzer, aber die for-Schleife geht noch ueber die urspruengliche Laenge.

Ausserdem ist for c in range(len(y)) unschoen, iteriere direkt ueber die Elemente!

Eine Loesung waere, eine dritte Liste in der Schleife neu zu erstellen. Falls x und y jeweils keine doppelten Elemente enthalten koennen, ginge es auch so:

Code: Alles auswählen

x = [1, 2, 3]
y = [1, 9, 8, 7]
for i in set(x) & set(y):
    y.remove(i)
EDIT: Verdammt, wie bekomme ich den ein einfaches Und-Zeichen in den Code? Der macht mir da html draus... :K
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Code: Alles auswählen

from operator import contains
from itertools import ifilterfalse
from functools import partial

l1 = range(4)
l2 = range(2,6)

print list(ifilterfalse(partial(contains, l2), l1))

[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Benutzeravatar
pillmuncher
User
Beiträge: 1531
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Ich würde es so machen:

Code: Alles auswählen

for each in x:
    while each in y:
        y.remove(each)
oder gleich deklarativ, also so:

Code: Alles auswählen

y = [each for each in y if each not in x]
[edit] if durch while ersetzt, damit alle und nicht nur jedes erste Vorkommen eines Elements aus x in y gelöscht werden.[/edit]
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was spricht gegen Mengen?

Code: Alles auswählen

In [18]: x = [1,2,3]

In [19]: y = [9,8,7,1]

In [20]: sx = set(x)

In [21]: sy = set(y)

In [22]: sy - sx
Out[22]: set([7, 8, 9])
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
pillmuncher
User
Beiträge: 1531
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Hyperion hat geschrieben:Was spricht gegen Mengen?
Solange die Reihenfolge oder die Frage, ob es Duplikate geben darf, keine Rolle spielt: nichts :)
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

Gegen Mengen spricht vielleicht die Reihenfolge. Wenn die erhalten bleiben soll:

Code: Alles auswählen

tmp = set(x)
y = [e for e in y if e not in tmp]
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

Außer der Reihenfolge könnte noch sein, dass nicht alle Elemente hashable sind.

Davon abgesehen ist BlackJacks Lösung m.E. die kanonische.
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

vielen Dank wiedereinmal für eure schnelle und qualifizierte Hilfe!

Ich habe pillmuchers Lösung verwendet.
Die anderen durchblicke ich nicht vollständig bzw. die verwendeten Befehle sind mir unbekannt.
Z.Z ist Python aber mehr Mittel zum Zweck um ein Problem zu lösen. Wenn ich damit durch bin, kann Python mal kurz Selbstzweck sein und ich kann mich mit den neuen Sachen beschäftigen.

Jetzt bin ich nur froh, dass mein riesen Programm langsam immer kompletter wird und das tut, was es soll :)
Antworten