Dictionary: kopieren key:value von einem dict in ein anderes

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
WalterT
User
Beiträge: 31
Registriert: Dienstag 5. Dezember 2017, 16:00

Hallo zusammen,
ich trau mich fast nicht fragen, die Lösung ist wahrscheinlich kinderleicht, aber ich komme nicht weiter und Freund Google findet auch nichts brauchbares.

Ich habe zwei Dictionarys und möchte ein key:value-Tuple von einem in das andere kopieren.
Das dict "elementlist" ist bereits befüllt, key ist ein Dateiname, value ist der lastmodify-Zeitstempel. Ich lege eine Schleife drüber. Wenn die Bedingung "beide Dateien existieren" erfüllt ist, soll das aktuelle key:value-Paar nach "elementlistcopy" kopiert werden. Am schluss wird "elementlisstcopy" wieder zu "elementlist".
Mein "Kopier"-Befehl ist falsch und ich finde die Syntax einfach nicht raus. Bitte um Hilfe.

Code: Alles auswählen

    # Dictonary aufräumen
    elementlistcopy.clear()
    for element in elementlist.keys():
        file_name, file_extension = os.path.splitext(element)
        file_name = file_name.strip()
        input_folder_element = os.path.join(INPUT_PATH, element)
        output_folder_element = os.path.join(OUTPUT_PATH, str(file_name + '.png'))
        if os.path.exists(input_folder_element) and os.path.exists(output_folder_element):
            elementlistcopy(element) = elementlist(element)
    elementlist = elementlistcopy.copy()
Benutzeravatar
sparrow
User
Beiträge: 4536
Registriert: Freitag 17. April 2009, 10:28

Schau dir mal .items() von dicts an.

Code: Alles auswählen

for element, last_modified in elementlist.items():
Benutzeravatar
__blackjack__
User
Beiträge: 14032
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@WalterT: Das Du bei `elementlistcopy` vorher `clear()` und hinterher `copy()` aufrufst ist ungewöhnlich und Datenstrukturen auf diese Weise wiederzuverwenden kann auch schwer zu findene Fehler zur Folge haben. Keine Angst vor neuen, frischen Objekten. Erstelle vor der Schleife einfach ein neues Wörterbuch, statt immer das selbe wiederzuverwenden.

Wenn man weder weiss wie man per Schlüssel auf Elemente von einem Wörterbuch zugreift, noch wie man zu einem Schlüssel einen Wert in ein Wörterbuch einträgt, sollte man dringend ein Grundlagentutorial durcharbeiten. In der Python-Dokumentation gibt es beispielsweise eines.

`str()` mit einer Zeichenkette aufzurufen ist sinnfrei – man hat ja bereits die Zeichenkette.

Der `strip()`-Aufruf sieht eigenartig aus. Kann das wirklich passieren das der Dateiname am Anfang und/oder Ende „whitespace“-Zeichen enthält und das die tatsächlich irrelevant sind? Wie sähe denn ein Beispiel für so einen Dateinamen aus?

Was Du da `element` nennst scheint ein Dateiname (komplett mit Pfad) zu sein – warum heisst das dann so generisch `element`? Und `elementlist` für ein *Wörterbuch*? Grunddatentypen sollten sowieso nicht in Namen vorkommen. Und schon gar nicht wenn es gar nicht stimmt!

Wenn man den Test in eine Funktion auslagert, braucht man kein `elementlistcopy` sondern kann das einfach als „dict comprehension“ ausdrücken:

Code: Alles auswählen

def source_and_target_exists(path):
    file_name, _ = os.path.splitext(path)
    file_name = file_name.strip()  # TODO Really?
    return (
        os.path.exists(os.path.join(INPUT_PATH, path))
        and os.path.exists(os.path.join(OUTPUT_PATH, file_name + '.png'))
    )

def ...():
    
    # Dictonary aufräumen
    path2last_modified = {
        path: last_modified
        for path, last_modified in path2last_modified.items()
        if source_and_target_exists(path)
    }
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
WalterT
User
Beiträge: 31
Registriert: Dienstag 5. Dezember 2017, 16:00

sparrow hat geschrieben: Mittwoch 17. Juli 2019, 12:32 Schau dir mal .items() von dicts an.

Code: Alles auswählen

for element, last_modified in elementlist.items():
hab ich mir angeschaut, bringt mir aber m.E. keine Lösung.
WalterT
User
Beiträge: 31
Registriert: Dienstag 5. Dezember 2017, 16:00

Danke für die ausführliche Antwort.

...ok, statt .clear() erstelle ich elementlistcopy immer neu, einverstanden. (Wozu gibts dann .clear())

Bitte keine Hinweise auf Grundlagenturorials, die habe ich durch. Das Problem dabei ist, dass diese Tutorials Dictoinarys immer mit echten Werten darstellen, das ist genau das, was ich nicht brauchen kann.

...ok, dann ohne str(), ich wusste nicht, dass join das kann

strip() ist wirklich überlfüssig an dieser Stelle.

Ich bleibe bei meinen variablen, auch wenn es nicht normgerecht ist.

Deinen Code verstehe ich leider nicht, da reichen meine Kenntnisse nicht aus.

Vielleicht könnte jemand einfach meine Frage beantworten. Im Grund ist das Problem, dass ich nicht herausfinde, wie man ein key:value-Tuple in einem Dict "anspricht" in seiner Gesamtheit.

Mein Code sieht jetzt so aus. Ich habe in Zeile 8 einiges ausprobiert, ohne Erfolg

Code: Alles auswählen

    # Dictonary aufräumen
    elementlistcopy = {}
    for element, last_modify in elementlist.items():
        file_name, file_extension = os.path.splitext(element)
        input_folder_element = os.path.join(INPUT_PATH, element)
        output_folder_element = os.path.join(OUTPUT_PATH, file_name, '.png')
        if os.path.exists(input_folder_element) and os.path.exists(output_folder_element):
            #
            # HIER KOMME ICH NICHT WEITER !! 
            # kopiere das Tuple element:last_modify in das Dict elementlistcopy
            #
    elementlist = elementlistcopy.copy()
Benutzeravatar
sparrow
User
Beiträge: 4536
Registriert: Freitag 17. April 2009, 10:28

Du solltest Hinweise, die dir gegeben werden, nicht einfach beiseite wischen.

Vielleicht solltest du dich mal von dem Wort kopieren trennen.
Ein Dictionary ist eine Kopplung von Values an Keys.
Du hast an der Stelle, wo du nicht weiter kommst, einen key an den Namen "element" und ein value an den Namen "last_modify" (ich würde es trotzdem modified nennen und den key auch nicht element, weil er kein Element beinhaltet).
Wie trägt man denn in einem dict einen Wert zu einem Key ein?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Code: Alles auswählen

dies_ist_ein_dict[und_das_hier_ein_schluessel] = jetzt_kommt_der_wert
Oder in deinem Fall

Code: Alles auswählen

 elementlistcopy[element] = last_modify
Sich Hinweise auf ein durchgearbeitetes Grundlagentutorial verbieten, wenn man sowas nicht beherrscht, finde ich schon bemerkenswert. Stattdessen sollen wir die hier nach Bedarf also in eigenen Worten nur fuer dich wiederholen?

Das copy() in der letzten Zeile ist ueberfluessig. elementlistcopy (besser: verified_filenames) ist schon ein neues dict. Davon nochmal eine Kopie zu machen ist ueberfluessig.
WalterT
User
Beiträge: 31
Registriert: Dienstag 5. Dezember 2017, 16:00

@sparrow
ich wische nichts beiseite, drum frage ich ja hier und nicht auf frag-mutti.de...

Ich hatte in meinem ursprünglichen Code die Zeile

Code: Alles auswählen

for element in elementlist.keys():
drinnen, und damit nur den key, nicht aber den value zur Verfügung. Ich dachte, zu einem Key gibt's immer einen Value und ich kann das Paar einfach kopieren.
Nach der Änderung auf

Code: Alles auswählen

for element, last_modified in elementlist.items():
hatte ich beides, wusste aber nicht, was ich damit anfange. Klar weiß ich, wie man was in ein Dictionary einträgt, ich schreib ja an anderer Stelle was in das dict "elementlist", aber ich bin nicht drauf gekommen, einfach

Code: Alles auswählen

elementlistcopy[element] = last_modify
zu schreiben.
Irgendwie wusste ich, dass es ganz einfach ist.

Ich habe mit Hinweise auf Grundlagentutorials nicht verbeten, sondern nur ersucht, das nicht zu tun. In vielen Foren liest man Hinweise wie RTFM (read the fucking Manual) oder GOOGLE IST DEIN FREUND. So was ist Verschwendung von Tastaturanschlägen.

Der copy() Befehl in der letzten Zeile ist nicht überflüssig, da das dict "elementlistcopy" als dict "elementlist" wieder verwendet werden muss. Aber vielleicht gibt's auch hier was richtigeres oder einfacheres. Ich werde Googlen und Tuts lesen....
Sirius3
User
Beiträge: 18266
Registriert: Sonntag 21. Oktober 2012, 17:20

@WalterT: es gibt kein dict "elementlist", oder ein dict "elementlistcopy" sondern nur Namen, die auf Objekte verweisen. "elementlistcopy" verweist auf ein Wörterbuch und Du machst eine Kopie und läßt "elementlist" darauf verweisen. Dann schmeißt Du das Original weg. Es ist also unsinnig, erst eine Kopie zu machen, wenn man gar nicht zwei unabhängige Exemplare braucht.
WalterT
User
Beiträge: 31
Registriert: Dienstag 5. Dezember 2017, 16:00

Ich brauche schon zwei unabhängige Exemplare, denn ich kann während der Iteration über elementlist nicht daraus entfernen. Daher baue ich eine Kopie mit jenen Einträgen, die ich behalten möchte und mache diese dann wieder zum Original.
Benutzeravatar
sparrow
User
Beiträge: 4536
Registriert: Freitag 17. April 2009, 10:28

Doch, die Kopie ist unsinnig.
Du kannst einfach dein Objekt an mehr als einen Namen binden.

Code: Alles auswählen

ein_name = name_für_anderes_objekt
Benutzeravatar
kbr
User
Beiträge: 1507
Registriert: Mittwoch 15. Oktober 2008, 09:27

@WalterT: nehmen wir an, Du hast ein Dictionary 'verified_filenames' (der von __deets__ vorgeschlagene Name bezeichnet den Inhalt korrekt) und möchtest den Inhalt erneut überprüfen. Dann kannst Du dies, ähnlich dem Beispiel von __blackjack__, in eine Funktion auslagern, in dieser Funktion ein *neues* Dictionary erstellen und dieses als Resultat zurückgeben:

Code: Alles auswählen

verified_filenames = verify_filenames(verified_filenames)
'verified_filenames' ist anschließend weiterhin ein Label auf ein Dictionary (wenngleich auch ein anderes Dictionary als vor dem Funktionsaufruf) mit der gewünschten Datenstruktur sowie den neuen überprüften Inhalten. Die Unabhängigkeit von Bezeichnern und Inhalten (d.h. von Objekten und deren Typen) ist eine Eigenschaft dynamisch typisierter Sprachen und somit auch für das Verständnis von Python wichtig.
Benutzeravatar
sparrow
User
Beiträge: 4536
Registriert: Freitag 17. April 2009, 10:28

WalterT hat geschrieben: Montag 22. Juli 2019, 06:22 Ich brauche schon zwei unabhängige Exemplare, denn ich kann während der Iteration über elementlist nicht daraus entfernen. Daher baue ich eine Kopie mit jenen Einträgen, die ich behalten möchte und mache diese dann wieder zum Original.
Wenn du die Aussage mit deinem Code vergleichst, wirst du übrigens feststellen, dass sie nicht stimmt.
Du iterierst erst über ein dict und machst _anschließend_ die Kopie.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@sparrow: das ist eine missverstaendliche Art, das auszudruecken.

Zuerstmal hat WalterT ja recht: ueber eine Collection iterieren waehrend sie man aendert ist bestenfalls ungeschickt, und schlimmstenfalls fuehrt es zu fehlern. Nur HAT er ja zwei unterschiedliche dict-Objekte: elementlist und elementlistcopy. Letzteres dann dem Namen des ersten zuzuweisen reicht. Das elementlistcopy.copy() ist ueberfluessig, weil es nur ein DRITTES erzeugt, das dann halt zugewiesen wird.
Antworten