Wie verändere ich recursiv den Value (v) einer Liste

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
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

Also, ich möchte den String in v verändern, das funktioniert wenn ich ihn direkt ausgebe aber nicht wenn ich den String v übergeben will. v ist kein String das ist klar, aber in was muss ich den String verpacken/ umwandeln damit er reinpasst?

Code: Alles auswählen


def changevalinlist(d):
  for k, v in d.iteritems():
    if isinstance(v, dict):
     changevalinlist(v)
    else: 
        # funktioniert
        print([w.replace('hallo', 'tschüs') for w in v])
        # das nicht
        v = [w.replace('hallo', 'tschüs') for w in v]
            
Hat jemand eine Idee?

Man findet überall nur Beispiel wo der Schlüssel(k) geändert wird weil das andere wohl trivial ist, ich aber nicht drauf komme. :-/
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Code: Alles auswählen

d[k] = [w.replace('hallo', 'tschüs') for w in v]
callsaender hat geschrieben:Man findet überall nur Beispiel wo der Schlüssel(k) geändert wird weil das andere wohl trivial ist, ich aber nicht drauf komme. :-/
Das glaube ich nicht, denn das ist bei einem Dictionary gar nicht möglich.

"changevalinlist" ist übrigens ein sehr seltsamer Name. Unnötige Abkürzung, hält sich nicht an PEP 8, sagt gar nichts über die Funktion aus und bekommt dann noch ein Dictionary übergeben in dem eine Liste geändert wird.
Das Leben ist wie ein Tennisball.
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

@EyDu
- der Name der Funktion hieß 'cleanup' und nicht 'changevalinlist'
- replaced wird " gegen \"

Ich wollte nicht verwirren, weil mit dem Entfernen von Zeichen wie
'double quote " ' noch andere Probleme mit kommen.
BlackJack

@callsaender: Ergänzend zu EyDu's Anmerkungen musst Du wenn Du das Wörterbuch veränderst über eine Liste mit den Schlüssel/Wert-Paaren iterieren, also `items()` statt `iteritems()`. Wenn man über Container-Objekte verändert, während man gleichzeitig über den Inhalt iteriert, ist nicht garantiert, dass man den kompletten Inhalt in der Schleife sieht.

Um die ``print``-Anweisung gehören in Python 2 keine Klammern. Es sei denn man hat den entsprechenden `__future__`-Import der aus der Anweisung eine Funktion macht oben im Modul stehen.

Bist Du immer noch dabei JSON-P-Dateien mit ungeeigneten Mitteln zu bearbeiten? :-)
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

Bist Du immer noch dabei JSON-P-Dateien mit ungeeigneten Mitteln zu bearbeiten? :-)
@BlackJack: ja :-)
.
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

Da habe ich noch ein Problem

Code: Alles auswählen

d[k] = [w.replace('hallo', 'tschüs') for w in v]
d[k] enthält jetzt zwar den String aber durch das 'for w in v' werden viele kleine Listeelemente erzeugt u't' u's' u'h' u'ü' u's' .......

Ich brauche aber etwas wie:

Code: Alles auswählen

w = str(d[k])
w.replace('hallo', 'tschüs')
d[k] = w
Zuletzt geändert von callsaender am Mittwoch 4. Dezember 2013, 15:03, insgesamt 1-mal geändert.
BlackJack

@callsaender: Wenn `v` gar keine Liste von Zeichenketten ist sondern selbst eine Zeichenkette, dann lass die „list comprehension” doch einfach weg. Eine Zeichenkette ist halt auch iterierbar → die Elemente sind die einzelnen Zeichen.

Wenn Du zwischen Zeichenkette und Liste unterscheiden musst, dann musst Du genau das an der Stelle halt machen: Zeichenketten anders als Listen behandeln. Also nur bei Zeichenketten die Ersetzung durchführen und bei Listen eine neue Liste erstellen auf deren Elemente die Funktion wieder rekursiv angewendet wird.
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

@BlackJack: Ich hoffe ich habe kappiert was 'list comprehension'

Code: Alles auswählen

         
        // Funktioniert 
        print d[k].replace('hallo', 'tschüs')
        // das aber nicht
        d[k] = d[k].replace('hallo', 'tschüs')
        print d[k]

Richtig wäre:
tschüs
tschüs

Aushabe:
tschüs
hallo

woran liegt es?
Zuletzt geändert von callsaender am Mittwoch 4. Dezember 2013, 16:16, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mit so kleinen Schnipseln können wird dir kaum helfen. Erstelle mal ein minimales *lauffähiges* Beispiel welches deinen Fehler produziert und poste das hier. Beim Kürzen deines Programms findest du wahscheinlich den Fehler schon selbst.
Das Leben ist wie ein Tennisball.
BlackJack

@callsaender: Das kann nicht sein. Wenn Du einen neuen Wert einem Schlüssel zuweist und der gleich danach nicht wieder auslesbar wäre, dann hätten Wörterbücher ein extrem heftiges Problem. Ich bin mir sicher das wäre schon mal jemandem vor Dir aufgefallen. ;-)
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

@EyDu : so hier hast du ein kleines lauffähiges Beispiel

Code: Alles auswählen

# -*- coding: cp1252 -*-
import sys
import codecs
import unicodedata
import io

dic = {"a":"schlecht"}

# recursion
def my_replace(d):
  for k, v in d.iteritems():
    if isinstance(v, dict):
     my_replace(v)
    else:
        print d[k].replace('schlecht', 'gut') 
        d[k].replace('schlecht', 'gut')
        print d[k]


my_replace(dic)

Das Ergebnis ist:
gut
schlecht

Aber es müsste raus kommen
gut
gut
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wozu die sinnlosen Imports? Die gehören in ein Minimalbeispiel nicht rein!
callsaender hat geschrieben:
Das Ergebnis ist:
gut
schlecht

Aber es müsste raus kommen
gut
gut
Nö!
Mal als Tipp:

Code: Alles auswählen

d = {"a": "schlecht"}

d["a"]
'schlecht'

'schlecht'.replace('schlecht', 'gut')
'gut'

d['a'].replace('schlecht', 'gut')
'gut'

d
{'a': 'schlecht'}
Du holst Dir den zu einem Schlüssel gehörigen Wert *aus* dem Dictionary und führst ``replace`` auf diesem aus. Du ersetzt aber eben *nicht* den Wert *im* Dictionary ;-)

Das geht per Zuweisung:

Code: Alles auswählen

d["a"] = "gut"
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@callsaender: Und zum drölftausendsten mal: Nicht über eine Datenstruktur iterieren *und* sie verändern. Undefiniertes Verhalten. Böse.
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

@Hyperion: Danke funzt

@BlackJack: Ich suche noch eine Lösung für das Problem !

Code: Alles auswählen

if language != 'de':
    for de_parent in tree.findall('.//de/..'):
        de_parent.remove(de_parent.find('de'))
bei der XML Geschichte habe ich ja schon gemacht. Bei der Pyhtonliste funktioniert das nicht so einfach! ???
BlackJack

@callsaender: Welches Problem? Welche Liste?
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

@BlackJack: wie würdest du das machen wenn nicht mit iteritems() oder iter() was man nicht einfach
hier ersetzen kann oder .findall() was ich in dieser "Datenstruktur" noch nicht hin bekommen habe ??
Und zum drölftausendsten mal: Nicht über eine Datenstruktur iterieren *und* sie verändern. Undefiniertes Verhalten. Böse.
Python Datenstruktur meinte ich !

z.B

d = {"a":{"b":{"c":"hello"}}}

wenn ich z.B. hello in hallo ändern möchte

Code: Alles auswählen

def my_replace(d):
  for k, v in d.iteritems():
    if isinstance(v, dict):
     my_replace(v)
    else:
       #change value of d[k]
BlackJack

@callsaender: Welche Methode man statt `iteritems()` verwenden muss habe ich hier schon geschrieben.
callsaender
User
Beiträge: 22
Registriert: Samstag 23. November 2013, 16:55

@BlackJack:
Ich hatte items() schon mal aus probiert und bekam eine Fehlermeldung die aber wo anders her kam, wie sich jetzt rausgestellt hat. Und ich verwende jetzt selbstverständlich 'item' wenn es dich beruhigt ;-)

@all
Es gibt das Kommentierungzeichen '#' in Python. In C kann man mehrere Zeilen gleichzeitig Kommentieren mit /* */ gibt es in Python ewas ähnliches ?

Hintergrung: Ich habe für den Rest des Projekts (nicht in Python geschrieben) sowas wie JavaDoc das die Kommentare raus filtert und in eine html Doku fasst.
BlackJack

@callsaender: Nein in Python gibt es nur # für Kommentare. Jeder brauchbare Editor kann damit aber auch Blöcke aus/einkommentieren. Für generierte Dokumentation wird in Python üblicherweise DocStrings verwendet. Die meisten Systeme erkennen auch noch spezielle Kommentare. Sphinx zum Beispiel wenn der Kommentar mit #: anfängt. Sphinx ist das Dokumentationswerkzeug mit dem unter anderem die Python-Dokumentation erstellt wird.
Antworten