Seite 1 von 2
l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Mittwoch 20. August 2014, 15:19
von jens
Wie kann ich aufeinander folgende Einträge in einer Liste durch einen anderen ersetzten?
also preudocode:
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Mittwoch 20. August 2014, 15:34
von EyDu
Für zwei Elemente:
Code: Alles auswählen
[("X" if x == (2, 3) else x) for (x, y) in zip(l, l[1:])]
Oder direkt eine ordentliche und allgemeine Funktion. Die ist wahrscheinlich keine zehn Zeilen lang.
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Mittwoch 20. August 2014, 15:35
von jens
Oh, super Idee! Mal testen...
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Mittwoch 20. August 2014, 15:40
von EyDu
Ein Problem mit meinem Ansatz gibt es natürlich dann, wenn zwei identische Werte ersetzt werden sollen. Also in einer Liste [1, 2, 2, 2, 3] der Werte [2, 2] ersetzt werden soll. Das ergäbe dann [1, X, X, 3].
Ach, und es muss natürlich
Code: Alles auswählen
[("X" if (x, y) == (2, 3) else x) for (x, y) in zip(l, l[1:])]
heißen, bzw. ohne Dekonstruktion:
Code: Alles auswählen
[("X" if elem == (2, 3) else elem[0]) for elem in zip(l, l[1:])]
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Mittwoch 20. August 2014, 15:46
von jens
Ne, so einfach ist das nicht:
Code: Alles auswählen
def list_replace_tuples(l, src, dst):
"""
>>> list_replace_tuples([1,2,3,4], (2,3), "X")
[1, 'X', 4]
>>> list_replace_tuples([1,2,3,4,5], (4,5), "X")
[1, 2, 3, 'X']
>>> list_replace_tuples([1,2,3,4,5], (1,2), "X")
['X', 3, 4, 5]
>>> list_replace_tuples([1,2,3,3,3,4,5], (3,3), "X")
[1, 2, 'X', 'X', 3, 4, 5]
"""
assert len(src)==2
return [
(dst if elem == src else elem[0]) for elem in zip(l, l[1:])
]
if __name__ == "__main__":
import doctest
print doctest.testmod()
Ausgabe:
Code: Alles auswählen
**********************************************************************
File "/media/servershare/workspace/DragonPy/dragonlib/core/test.py", line 3, in __main__.list_replace_tuples
Failed example:
list_replace_tuples([1,2,3,4], (2,3), "X")
Expected:
[1, 'X', 4]
Got:
[2, 'X', 4]
**********************************************************************
File "/media/servershare/workspace/DragonPy/dragonlib/core/test.py", line 6, in __main__.list_replace_tuples
Failed example:
list_replace_tuples([1,2,3,4,5], (4,5), "X")
Expected:
[1, 2, 3, 'X']
Got:
[2, 3, 4, 'X']
**********************************************************************
File "/media/servershare/workspace/DragonPy/dragonlib/core/test.py", line 12, in __main__.list_replace_tuples
Failed example:
list_replace_tuples([1,2,3,3,3,4,5], (3,3), "X")
Expected:
[1, 2, 'X', 'X', 3, 4, 5]
Got:
[2, 3, 'X', 'X', 4, 5]
**********************************************************************
1 items had failures:
3 of 4 in __main__.list_replace_tuples
***Test Failed*** 3 failures.
TestResults(failed=3, attempted=4)
Man kann auch statt elem[0] auch elem[1] nehmen. Aber dann fehlt halt der andere Teil...
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Mittwoch 20. August 2014, 15:52
von EyDu
Da has du natürlich Recht. Ein wenig Nachdenken vor dem Posten hätte wohl geholfen

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Mittwoch 20. August 2014, 15:57
von EyDu
Code: Alles auswählen
def replace(l, old, new):
index = 0
while index < len(l):
element = l[index:index+len(old)]
if element == old:
yield new
index += len(old)
else:
yield l[index]
index += 1
Natürlich wieder ungetestet.
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Mittwoch 20. August 2014, 16:06
von jens
Treffer:
Code: Alles auswählen
def list_replace_tuples(l, src, dst):
"""
>>> list_replace_tuples([1,2,3,4], (2,3), "X")
[1, 'X', 4]
>>> list_replace_tuples([1,2,3], (2,), "X")
[1, 'X', 3]
>>> list_replace_tuples([1,2,3,4,5], (2,3,4), "X")
[1, 'X', 5]
>>> list_replace_tuples([1,2,3,4,5], (4,5), "X")
[1, 2, 3, 'X']
>>> list_replace_tuples([1,2,3,4,5], (1,2), "X")
['X', 3, 4, 5]
>>> list_replace_tuples([1,2,3,3,3,4,5], (3,3), "X")
[1, 2, 'X', 3, 4, 5]
"""
result=[]
src=list(src)
src_len=len(src)
index = 0
while index < len(l):
element = l[index:index+src_len]
#print element, src
if element == src:
result += dst
index += src_len
else:
result.append(l[index])
index += 1
return result
if __name__ == "__main__":
import doctest
print doctest.testmod()
Test läuft durch

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 01:22
von snafu
Code: Alles auswählen
def iter_replace(iterable, needle, replacement):
"""
>>> list(iter_replace([1,2,3,4], (2,3), "X"))
[1, 'X', 4]
>>> list(iter_replace([1,2,3], (2,), "X"))
[1, 'X', 3]
>>> list(iter_replace([1,2,3,4,5], (2,3,4), "X"))
[1, 'X', 5]
>>> list(iter_replace([1,2,3,4,5], (4,5), "X"))
[1, 2, 3, 'X']
>>> list(iter_replace([1,2,3,4,5], (1,2), "X"))
['X', 3, 4, 5]
>>> list(iter_replace([1,2,3,3,3,4,5], (3,3), "X"))
[1, 2, 'X', 3, 4, 5]
"""
picked = []
for item in iterable:
if item == needle[len(picked)]:
picked.append(item)
if len(picked) == len(needle):
del picked[:]
yield replacement
else:
for picked_item in picked:
yield picked_item
del picked[:]
yield item
if __name__ == "__main__":
import doctest
print doctest.testmod()
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 09:12
von Sirius3
@snafu: der Testfall
Code: Alles auswählen
>>> list(iter_replace([1,2,2,3,4,5],[2,3], "X"))
[1, 2, 2, 3, 4, 5]
fehlt, richtig wäre:
Code: Alles auswählen
>>> list(iter_replace([1,2,2,3,4,5],[2,3], "X"))
[1, 2, 'X', 4, 5]
Hier eine Variante mit deque:
Code: Alles auswählen
from collections import deque
from itertools import islice
def iter_replace(iterable, needle, replacement):
"""
>>> list(iter_replace([1,2,3,4], (2,3), "X"))
[1, 'X', 4]
>>> list(iter_replace([1,2,3], (2,), "X"))
[1, 'X', 3]
>>> list(iter_replace([1,2,3,4,5], (2,3,4), "X"))
[1, 'X', 5]
>>> list(iter_replace([1,2,3,4,5], (4,5), "X"))
[1, 2, 3, 'X']
>>> list(iter_replace([1,2,3,4,5], (1,2), "X"))
['X', 3, 4, 5]
>>> list(iter_replace([1,2,3,3,3,4,5], (3,3), "X"))
[1, 2, 'X', 3, 4, 5]
>>> list(iter_replace([1,2,2,3,4,5], (2,3), "X"))
[1, 2, 'X', 4, 5]
"""
iterable = iter(iterable)
needle = deque(needle)
picked = deque(islice(iterable, len(needle)-1))
for item in iterable:
picked.append(item)
if needle == picked:
yield replacement
picked = deque(islice(iterable, len(needle)-1))
else:
yield picked.popleft()
for item in picked:
yield item
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 09:43
von snafu
Erweiterung meiner Variante:
Code: Alles auswählen
def iter_replace(iterable, needle, replacement):
"""
>>> list(iter_replace([1,2,3,4], (2,3), "X"))
[1, 'X', 4]
>>> list(iter_replace([1,2,3], (2,), "X"))
[1, 'X', 3]
>>> list(iter_replace([1,2,3,4,5], (2,3,4), "X"))
[1, 'X', 5]
>>> list(iter_replace([1,2,3,4,5], (4,5), "X"))
[1, 2, 3, 'X']
>>> list(iter_replace([1,2,3,4,5], (1,2), "X"))
['X', 3, 4, 5]
>>> list(iter_replace([1,2,3,3,3,4,5], (3,3), "X"))
[1, 2, 'X', 3, 4, 5]
>>> list(iter_replace([1,2,2,3,4,5], (2,3), "X"))
[1, 2, 'X', 4, 5]
"""
picked = []
for item in iterable:
if item == needle[len(picked)]:
picked.append(item)
if len(picked) == len(needle):
del picked[:]
yield replacement
elif len(picked) == 1 and item == picked[0]:
yield item
else:
for picked_item in picked:
yield picked_item
del picked[:]
yield item
if __name__ == "__main__":
import doctest
print doctest.testmod()
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 10:41
von Sirius3
@snafu: dann kannst Du gleich auf 2-elementige Wiederholungen im Pattern erweitern
Code: Alles auswählen
>>> list(iter_replace([1,2,3,2,3,2,3,3,4,5], (2,3,2,3,3), 'X'))
[1, 2, 3, 2, 3, 2, 3, 3, 4, 5]
statt
Code: Alles auswählen
>>> list(iter_replace([1,2,3,2,3,2,3,3,4,5], (2,3,2,3,3), 'X'))
[1, 2, 3, 'X', 4, 5]
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 11:41
von snafu
Nagut...

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 12:55
von jens
Ob man das nicht eigentlich als Feature Request einreichen könnte? Also ein l=l.replace([2,3], "X") ?
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 13:41
von BlackJack
@jens: Unter welchem Namen? `replace()` geht ja nicht, das gibt es schon und das hat für diese Argumente bereits eine Bedeutung.
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 13:48
von jens
Warum nicht replace? Eine liste hat doch kein replace, oder was meinst du?
Halt das selbe was string.replace macht (pseudocode):
Code: Alles auswählen
s="12345"
print s.replace("3","X")
"12X45"
l=[1,2,3,4,5]
print l.replace(3,"X")
[1,2,"X",4,5]
print l.replace([2,3,4],"Y")
[1,"Y",5]
print l.replace([2,3,4],["X","Y"])
[1,"X","Y",5]
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 13:56
von BlackJack
@jens: Ups, die Methode gibt's tatsächlich nicht. Aber die wäre *so* für mich unerwartet. Ich hätte erwartet das die beiden Argumente das alte und das neue Element sind, also bei ``print l.replace([2,3,4],"Y")`` hätte ich keine Änderung erwartet weil in der Liste kein Element mit dem Wert [2,3,4] vorkommt. Bei ``l = [42, [2, 3, 4], 'spam']`` würde ich dann allerdings [42, 'Y', 'spam'] als Ergebnis erwarten.
Das heisst eigentlich jedes mal `None` denn `replace()` verändert ja die Liste und erstellt keine neue. (Oder?)
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 14:12
von jens
Mein das so:
Code: Alles auswählen
class List2(list):
def replace(self, src, dst):
"""
>>> l=List2([1,2,3,4])
>>> l
[1, 2, 3, 4]
>>> l.replace((2,3), "X")
[1, 'X', 4]
>>> l=List2([1,2,3,4])
>>> l.replace([2], "X")
[1, 'X', 3, 4]
>>> l=List2([1,2,3,4,5])
>>> l.replace([2,3,4], "X")
[1, 'X', 5]
>>> l=List2([1,2,3,4,5])
>>> l.replace((4,5), "X")
[1, 2, 3, 'X']
>>> l=List2([1,2,3,4,5])
>>> l.replace((1,2), "X")
['X', 3, 4, 5]
>>> l=List2([1,2,3,3,3,4,5])
>>> l.replace((3,3), "X")
[1, 2, 'X', 3, 4, 5]
"""
result=[]
src=list(src)
src_len=len(src)
index = 0
while index < len(self):
element = self[index:index+src_len]
#print element, src
if element == src:
result += dst
index += src_len
else:
result.append(self[index])
index += 1
return result
if __name__ == "__main__":
import doctest
print doctest.testmod(verbose=0)
print " --- END --- "
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 14:14
von BlackJack
@jens: Habe das schon verstanden, aber das finde ich sehr komisch. Ich hätte da etwas anderes erwartet.
Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
Verfasst: Donnerstag 21. August 2014, 14:16
von jens
Ist doch das selbe verhalten wie ein str.replace() oder?