Seite 2 von 2

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 15:20
von BlackJack
@jens: Ja, aber Listen sind keine Zeichenketten. Ich hätte halt erwartet das das erste Argument das Element ist welches man ersetzen will und das zweite wodurch es ersetzt wird. Wie würdest Du denn *so* eine Methode nennen wenn Deine schon `replace()` heisst? Und da Listen veränderbar sind, hätte ich erwartet das die Liste verändert wird und nicht eine neue zurück gegeben wird. Dazu hätte die Methode `replaced()` heissen müssen. Bei Zeichenketten geht es ja nicht anders weil die unveränderbar sind.

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 15:26
von jens
BlackJack hat geschrieben: Ich hätte halt erwartet das das erste Argument das Element ist welches man ersetzen will und das zweite wodurch es ersetzt wird.
Hä? Das ist doch genau so auch gemacht. Schau noch mal die DocTests vom letzten code.
BlackJack hat geschrieben:Und da Listen veränderbar sind, hätte ich erwartet das die Liste verändert wird und nicht eine neue zurück gegeben wird.
Das stimmt, wäre auch eine sehr gute Idee!

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 15:39
von BlackJack
@jens: Nein das macht Dein Code eben nicht. Da gibst Du als erstes Argument kein Element sondern eine Teilsequenz an. Das finde ich überraschend, denn wenn ich etwas mit `replace()` austausche erwarte ich zum Beispiel das ich mit ``in`` prüfen könnte ob es überhaupt enthalten ist. Mit ``in`` kann ich bei Listen aber nur einzelne Elemente prüfen und keine Teilsequenzen. Ich würde das nicht `replace()` sondern beispielsweise `replace_sequence()` nennen. Und auch erwarten das beide Argumente Sequenzen sind.

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 15:45
von jens
Aber das mit dem ``in`` ist doch genauso doof. Warum kann ich nicht sagen: if [2,3] in [1,2,3,4]: Wäre doch auch nett!

Nun wird die selbe Liste nur modifiziert und zurück geliefert:

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]

        >>> l=List2(["A",1,2,"B",1,2,"C"])
        >>> l.replace((1,2), "*")
        ['A', '*', 'B', '*', 'C']

        >>> l=List2(["X", 1,2,3, 1,2,3, 1,2,3, "Y"])
        >>> l.replace([1,2,3], ".")
        ['X', '.', '.', '.', 'Y']

        >>> l=List2([(1,2),(3,4), (5,6), (1,2),(3,4)])
        >>> l.replace([(1,2), (3,4)], "X")
        ['X', (5, 6), 'X']
        """
        src=list(src)
        src_len=len(src)
        dst_len=len(dst)
        index = 0
        while index < len(self):
            element = self[index:index+src_len]
            if element == src:
                del(self[index:index+src_len])
                self.insert(index, dst)
                index += dst_len
            else:
                index += 1
        return self


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, 15:47
von jens
Und warum geht das nicht:

Code: Alles auswählen

l=[1,2,3,4,5]
print l.index([3,4])

Traceback (most recent call last):
  File "test.py", line 60, in <module>
    print l.index([3,4])
ValueError: [3, 4] is not in list

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 16:02
von jens
So, auch index, und __contains__ mit gemacht:

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]

        >>> l=List2(["A",1,2,"B",1,2,"C"])
        >>> l.replace((1,2), "*")
        ['A', '*', 'B', '*', 'C']

        >>> l=List2(["X", 1,2,3, 1,2,3, 1,2,3, "Y"])
        >>> l.replace([1,2,3], ".")
        ['X', '.', '.', '.', 'Y']

        >>> l=List2([(1,2),(3,4), (5,6), (1,2),(3,4)])
        >>> l.replace([(1,2), (3,4)], "X")
        ['X', (5, 6), 'X']
        """
        src=list(src)
        src_len=len(src)
        dst_len=len(dst)
        index = 0
        while index < len(self):
            element = self[index:index+src_len]
            if element == src:
                del(self[index:index+src_len])
                self.insert(index, dst)
                index += dst_len
            else:
                index += 1
        return self

    def __contains__(self, item):
        """
        >>> [2,3] in List2([1,2,3,4])
        True

        >>> (2,3) in List2([1,2,3])
        True

        >>> 2 in List2([1,2,3])
        True
        """
        if not isinstance(item, (list, tuple)):
            return super(List2, self).__contains__(item)

        if not isinstance(item, list):
            item=list(item)

        item_len=len(item)
        for index in xrange(len(self)):
            element = self[index:index+item_len]
            if element == item:
                return True
        return False

    def index(self, item):
        """
        >>> List2([1,2,3,4]).index([2,3])
        1

        >>> List2([1,2,3,4]).index((3,4))
        2

        >>> List2([1,2,3]).index("X")
        Traceback (most recent call last):
        ...
        ValueError: 'X' is not in list

        >>> List2([1,2,3]).index([5,6])
        Traceback (most recent call last):
        ...
        ValueError: [5, 6] is not in list
        """
        if not isinstance(item, (list, tuple)):
            return super(List2, self).index(item)

        if not isinstance(item, list):
            item=list(item)

        item_len=len(item)
        for index in xrange(len(self)):
            element = self[index:index+item_len]
            if element == item:
                return index
        raise ValueError("%r is not in list" % item)


if __name__ == "__main__":
    import doctest
    print doctest.testmod(verbose=0)
    print " --- END --- "

Was fehlt da noch?


EDIT: Der Code ist nun auch hier: https://gist.github.com/jedie/a1c25c520dc314340c26

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 16:18
von Sirius3
Was erwartet man bei so einer Liste?

Code: Alles auswählen

l = [1, 2, 3, 4, [2, 3]]
l.replace([2,3], "X")
oder noch verwirrender:

Code: Alles auswählen

l = ['A', 'B', 'C', 'ABC']
l.replace('ABC', 'X')

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 16:24
von jens
Aktuell passiert das:

Code: Alles auswählen

l=List2([1, 2, 3, 4, [2, 3]])
print l.replace([2,3], "X") # -> [1, 'X', 4, [2, 3]]
print l.replace([[2,3]], "X") # -> [1, 'X', 4, 'X']

l=List2(['A', 'B', 'C', 'ABC'])
print l.replace('ABC', 'X') # -> ['X', 'ABC']
Wobei l.replace([[2,3]], "X") # -> [1, 'X', 4, 'X'] hätte ich nicht erwartet. Sondern: l.replace([[2,3]], "X") # -> [1, 2, 3, 4, 'X']

EDIT: Nett ist doch das:

Code: Alles auswählen

        >>> List2([1, 2, 3, 4]).replace([2,3], ["X","Y"])
        [1, ['X', 'Y'], 4]
Ich finde, dadurch das keine "Sonderbehandlungen" stattfinden, ist das doch eine saubere Sache.

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 16:37
von jens
jens hat geschrieben:Aktuell passiert das:

Code: Alles auswählen

l=List2([1, 2, 3, 4, [2, 3]])
print l.replace([2,3], "X") # -> [1, 'X', 4, [2, 3]]
print l.replace([[2,3]], "X") # -> [1, 'X', 4, 'X']
Wobei ich das so falsch verstanden hab :oops:
Hier wird die Liste ja zuerst vorn, dann im zweite Beispiel hinten geändert. Also alles gut:

Code: Alles auswählen

        >>> List2([1, 2, 3, 4, [2, 3]]).replace([2,3], "X")
        [1, 'X', 4, [2, 3]]

        >>> List2([1, 2, 3, 4, [2, 3]]).replace([[2,3]], "X")
        [1, 2, 3, 4, 'X']
Hab die Beispiele mal mit Aufgenommen:
https://gist.github.com/jedie/a1c25c520 ... /revisions


Also nochmal die Frage, was spricht dagegen?
Das man es in der Praxis ehr wenig braucht?

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Donnerstag 21. August 2014, 21:45
von BlackJack
@jens: Ich weiss nicht ob es was bringt das ich *nochmal* wiederhole das die Funktion/Methode IMHO etwas unerwartetes macht.

Re: l=[1,2,3,4] ; l=l.replace([2,3], "X") ???

Verfasst: Freitag 22. August 2014, 07:07
von jens
BlackJack hat geschrieben: 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.
Jetzt verstehe ich was du meinst!

Stimmt, wie wäre es mit einer 'normalen' replace Methode, die so wie du es erwartest arbeitet und meine Varianten umbenennen in z.b.: seq_replace, seq_index und seq_contains...