Seite 1 von 2
listen replace
Verfasst: Donnerstag 13. August 2009, 14:22
von 4bit
Hallo da,
habt ihr eigene Listen definiert oder benutzt ihr Prozeduren, um Elemente in Listen zu ersetzten?
So sieht derzeit eine Funktion aus, die ich benutze um eine neue Kopie mit allen Ersetzungen zurückzugeben, aber glücklich bin ich damit nicht..
Code: Alles auswählen
def replace(a, b, liste):
copy = list(liste)
for e in copy:
if e == a: copy[copy.index(e)] = b
return copy
praktischer wäre eine Methode replace. Andererseits möchte ich eine eigene Klasse my_list wenn möglich umgehen. Gibts da einen Zwischenweg?
grüße,
4bit-
Verfasst: Donnerstag 13. August 2009, 14:35
von cofi
Besser mit ``deepcopy`` kopieren.
Ich wuerde einen Test vorschieben, ob ``a`` ueberhaupt in der Liste ist und dann mit ``index`` ``a`` suchen.
Ungetestet:
Code: Alles auswählen
def replace(old, new, list_):
list_ = copy.deepcopy(list_)
if old in list_:
position = 0
try:
while position <= len(list_):
index = list_.index(old, position)
list_[index] = new
position = index
except ValueError:
return list_
else:
return list_
Der ``position`` Kram muss leider sein, um auch wirklich alle Treffer zu finden.
Verfasst: Donnerstag 13. August 2009, 15:02
von 4bit
ok, läuft.
Ohne größere Verwirrung Stiften zu wollen: Hab die Funktion jetzt doch als Prozedur geschrieben:
Code: Alles auswählen
def replace(a, b, liste):
for e in liste:
if e == a: liste[liste.index(e)] = b
und die if-Abfrage weg gelassen, weil der "for e in liste" Loop nicht Rechenaufwendig ist (eine if-Abfrage für jedes Element. Eine "a in liste"-Abfrage dauert wahrscheinlich auch eine if-Abfrage "für jedes Element in Liste" lange, also etwas gleich lang).
Wenn ich aber iteriere und replace auf die...
man, jetzt funktioniert das doch. Also danke. Meine Fragen haben sich gerade von selbst beantwortet.
Verfasst: Donnerstag 13. August 2009, 15:12
von sma
Code: Alles auswählen
def replace(lst, a, b):
return [b if e == a else e for e in lst]
Stefan
Verfasst: Donnerstag 13. August 2009, 15:26
von EyDu
Da kann man doch noch wertvollen Festplattenspeicher sparen! ^^
Code: Alles auswählen
def replace(lst, a, b):
return [(e,b)[e == a] for e in lst]
@4bit und cofi: Ihr steht nicht so auf "enumerate", oder?
Verfasst: Donnerstag 13. August 2009, 15:41
von cofi
EyDu hat geschrieben:@4bit und cofi: Ihr steht nicht so auf "enumerate", oder?
Naja da ich nicht ueber die Liste iteriere, braeuchte ich eine extra Liste. Die Index Zeilen sind zwar unschoen, aber ich will mir gar nich die ``enumerate``-Version vorstellen.
@4bit: Stimmt, Membership-Testing hat in Listen lineare Laufzeit. Evtl ist der Test auf ein Set trotzdem schneller als der naive Ansatz (kommt natuerlich auf die Daten an), gilt auch fuer die LC Versionen.
Uebrigens kannst du das auch den Listen anhaengen:
Code: Alles auswählen
def replace(self, old, new):
if old in set(self):
return [new if e == old else e for e in self]
else:
return self
list.replace = replace
Empfohlen hab ich das aber nicht

Verfasst: Donnerstag 13. August 2009, 15:57
von 4bit
@cofi: Danke. Gut zu wissen, falls ich doch noch nachträglich eingreifen möchte.
Verfasst: Donnerstag 13. August 2009, 16:52
von EyDu
cofie hat geschrieben:Die Index Zeilen sind zwar unschoen, aber ich will mir gar nich die ``enumerate``-Version vorstellen.
Schwer vorstellbar? Übersehe ich irgendwelche wichtigen Features?
Code: Alles auswählen
def replace(sequence, old, new):
for index, element in enumerate(sequence):
if element == old:
sequence[index] = new
return sequence
Ich habe die Laufzeit nicht getestet, aber asymptotisch ist ein vorheriger Test auf Enthaltensein unnötig.
Verfasst: Donnerstag 13. August 2009, 16:59
von cofi
EyDu hat geschrieben:Übersehe ich irgendwelche wichtigen Features?
Naja, wie gesagt: Ich iteriere nicht ueber die Liste.
Aber ich merke gerade, dass die Pruefung bei der while-Schleife ueberfluessig ist, da sie eh durch den ``ValueError`` beendet wird.
Verfasst: Donnerstag 13. August 2009, 17:09
von EyDu
cofi hat geschrieben:Naja, wie gesagt: Ich iteriere nicht ueber die Liste.
Naja, zumindest hast du es mit "list.index" sehr gut versteckt ^^
Verfasst: Freitag 14. August 2009, 09:32
von 4bit
@ EyDu: enumerate kannte ich nicht, ist aber praktisch. Habe häufiger die Situation, daß ich zwei Listen habe, deren Elemente zusammengehören, wenn sie die gleichen Indizies haben. Sowas:
Code: Alles auswählen
menge = [1,2,3,4]
zeichen = ["+", "-", "+", "+"]
for ding in menge
if zeichen[menge.index(ding)] == "-": print "oh no!"
Das geht mit enumerate übersichtlicher:
Code: Alles auswählen
for i, ding in enumerate(menge):
if zeichen[i] == "-": print "huch!"
was bei den Beispielen nicht so gut rüber kommt ist, daß von Anfang an über den Index gehen (mit "range(len(menge))") manchmal nicht so übersichtlich ist. Zum Beispiel wenn "menge" aus komplizierteren Dingen besteht als Integers, die man selbst wieder per index auswählt.
In jedem Fall ist enumerate praktisch, weil sozusagen die Iteration über den Index sowie die Index-freie Iteration über die Elemente gleichzeitig zur Verfügung stehen.
Verfasst: Freitag 14. August 2009, 09:38
von Hyperion
@4bit: Wobei Deine beiden Beispiele hier sich viel einfache lösen ließen, da Du menge und zeichen quasi nicht miteinander verknüpfst:
Will man die beiden Mengen verknüpfen würde ich das ggf. auch mit zip lösen:
Code: Alles auswählen
menge = [1,2,3,4]
zeichen = ["+", "-", "+", "+"]
for element, token in zip(menge, zeichen):
if element == "-":
print element, token
Verfasst: Freitag 14. August 2009, 09:59
von 4bit
@Hyperion: aha. Also "zip" und "enumerate" machen in diesem Fall für den Programmierer keinen Unterschied. "zip" ist wohl etwas allgemeiner als "enumerate".
man könnte meinen, daß
gilt. (Aber das eine gibt eine Liste zurück und enumerate ein "enumerate-Objekt").
Verfasst: Freitag 14. August 2009, 13:18
von Hyperion
4bit hat geschrieben:@Hyperion: aha. Also "zip" und "enumerate" machen in diesem Fall für den Programmierer keinen Unterschied. "zip" ist wohl etwas allgemeiner als "enumerate".
Hm... naja, zip und enumerate sind zwei vollkommen verschiedene Sachen. Enumerate erzeugt zu einer Liste einen Index und zip vereinigt einfach die Elemente aus zwei Listen zu Paaren. Da Deine eine Liste im Beispiel nur aus aufsteigenden Zahlen besteht, sieht das Ergebnis natürlich ähnlich aus.
Verfasst: Freitag 14. August 2009, 19:33
von BlackJack
@4bit: ``enumerate(liste)`` entspricht eher ``izip(count(), liste)`` mit `izip()` und `count()` aus dem `itertools`-Modul.
Ich habe so ein bisschen das Gefühl, dass Du Python nicht "richtig" verwendest, denn ich hatte soweit ich mich erinnere noch nie Verwendung für so eine `replace()`-Prozedur, ich schreibe da lieber Funktionen, noch verschiedene Listen wo die Elemente eigentlich zusammen gehören.
Verfasst: Samstag 15. August 2009, 22:41
von Pascal
Es gibt auch die Möglichkeit das ganze mit der replace-Methode für strings zu lösen.
Hier ist mein Ansatz:
Code: Alles auswählen
>>> def replace(liste, old, new):
return (str(liste).replace(str(old), str(new))).split('[')[1].split(']')[0].split(', ')
>>> replace(range(10), 4, 0)
['0', '1', '2', '3', '0', '5', '6', '7', '8', '9']
Verfasst: Sonntag 16. August 2009, 07:34
von hendrikS
Pascal hat geschrieben:Es gibt auch die Möglichkeit das ganze mit der replace-Methode für strings zu lösen.
Nichts fuer ungut, Dein Beispiel ist aber am Ende nicht mehr als Spielerei. Dein Code ist uneffizient und unflexibel. Wuerde niemand so machen.
Verfasst: Sonntag 16. August 2009, 10:31
von EyDu
@Pascal: dafür müsstest du aber "funktioniert" ganz neu definieren.
Verfasst: Sonntag 16. August 2009, 18:11
von Pascal
hendrikS hat geschrieben:Pascal hat geschrieben:Es gibt auch die Möglichkeit das ganze mit der replace-Methode für strings zu lösen.
Nichts fuer ungut, Dein Beispiel ist aber am Ende nicht mehr als Spielerei. Dein Code ist uneffizient und unflexibel. Wuerde niemand so machen.
Ich wollt ja lediglich einen anderen Lösungsvorschlag präsentieren.
Und das es auch bei komplexeren Listen nicht ganz funktinoniert hat ja EyDu schon gezeigt

Verfasst: Sonntag 16. August 2009, 19:45
von BlackJack
@Pascal: Das ist vielleicht ein Vorschlag gewesen, aber keine Lösung. Wenn man eine Sprache haben möchte, bei Datenstrukturen über Zeichenketten simuliert werden, sollte man Shell- oder Tcl-Skripte schreiben, aber bitte nicht Python.
