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

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.
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.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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!

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
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.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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 --- "

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

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')
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Ich weiss nicht ob es was bringt das ich *nochmal* wiederhole das die Funktion/Methode IMHO etwas unerwartetes macht.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten