Dictionaries Werte mit gleichem schlüssel verbinden

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
Ambriador
User
Beiträge: 35
Registriert: Freitag 25. November 2016, 01:05

Hallo an alle,

leider komme ich bei einer Uni Aufgabe nicht weiter.
Ich habe zwei dicts die verbunden werden sollen, allerdings nur die bei denen die keys gleich sind.

Als Beispiel:

Code: Alles auswählen

matrikelnummer_zu_note = { 35135135: 5, 60103513: 3, 10981179: 2, 18637724 : 4 }
note_zahl_zu_string = { 1: "summa cum laude", 2: "magna cum laude", 3: "cum laude", 4: "rite", 5: "non probatum" }
soll zu

Code: Alles auswählen

{60103513: 'cum laude', 10981179: 'magna cum laude', 18637724: 'rite', 35135135: 'non probatum'}
werden. Dazu soll die map() Funktion mit Lambda Ausdruck verwendet werden. Leider habe ich keine Ahnung wie ich da sinnvoll eine map() Funktion mit Lambda einbauen soll?
Mit map() kann ich ja eigentlich nur Listen erstellen, bzw wie kann ich dann vergleichen ob die Keys in den dicts gleich sind?

Viele Grüße
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Ambriador: Aus einer Liste mit (key, value) kann man einfach wieder ein Wörterbuch bauen.
Ambriador
User
Beiträge: 35
Registriert: Freitag 25. November 2016, 01:05

Also muss ich aus den beiden dicts erst Listen machen, und anschliessend wieder dicts?
BlackJack

@Ambriador: Nein, Du musst eine Liste mit den gewünschten Tupeln erstellen und daraus dann das neue Wörterbuch. Beziehungsweise brauchst Du die Liste nicht, es reicht auch ein Iterator der die liefert.
Benutzeravatar
pyHoax
User
Beiträge: 84
Registriert: Donnerstag 15. Dezember 2016, 19:17

oder so:

Code: Alles auswählen

matrikel_zu_noten_string= { matrikelnummer: note_zahl_zu_string[note] for matrikelnummer, note in matrikelnummer_zu_note.items() }
Einer meiner Lieblingsfeatures in Python.. ist das nicht ein schöner Ausdruck ?
BlackJack

Nö, finde ich nicht schön. Die Syntax ist als sie eingeführt wurde nicht wirklich nötig gewesen weil sie kein Problem gelöst hat. Schreib `dict` vor die geschweifte Klammer, mach aus den geschweiften Klammern runde Klammern, und aus dem ``schlüssel: wert``-Teil ein Tupel ``(schlüssel, wert)`` und Du hast den gleichen Effekt mit weniger zusätzlicher Syntax. Man muss ja mittlerweile genauer hinschauen was etwas in geschweiften Klammern tatsächlich bedeutet. Das war mal nur ein Wörterbuch-Literal. Mittlerweile kann es Wörtebuch-Literal, Mengen-Literal, „set comprehension“, oder „dict comprehension“ sein.
Benutzeravatar
pyHoax
User
Beiträge: 84
Registriert: Donnerstag 15. Dezember 2016, 19:17

Man muss ja mittlerweile genauer hinschauen was etwas in geschweiften Klammern tatsächlich bedeutet.
Abgsehen davon das ein Dictonary neben den Klammern auch ein Key-wert Mapping hat an den man es erkennt .. die Klammerung ist doch absolut konsistent für Dicts und die for .. in Schreibweise macht es nur schwer mit den Literalen des selben Datentyps verwechselbar.

Die dict-comprehension finde ich einfach großartiger als die für listen weil listen mapping syntaktisch im Gegensatz zu Wörterbüchern trivial ist. (Allgemein gesprochen)
Die in Python verwendetet Notation ist meine Meinung vorbildlich, informativ und esthetisch. (Da kann man natürlich streiten)

Aus technischer Sicht sind die iterator Ausdrücke der Hit, zurückblickend wäre ich damit aber schnhttps://www.python-forum.de/viewforum.php?f=1eller klargekommen wenn der Synatx explizieter gewesen wäre und sich vom list Synatx z.B durch ein iter Keywort abheben würde.

Das andere Notation damit interferieren tut mir leid, das ändert nichts an ihrer Eleganz.
n.
Ambriador
User
Beiträge: 35
Registriert: Freitag 25. November 2016, 01:05

Danke für die Antwort.
Wie baue ich da am besten dann noch die map() FUnktion ein? Bin leider echt überfragt :K
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

Ambriador hat geschrieben:Danke für die Antwort.
Wie baue ich da am besten dann noch die map() FUnktion ein? Bin leider echt überfragt :K
Die Aufgabe ist in einer Zeile lösbar, aber vielleicht etwas kniffelig, da man ein bisschen mit Datenstrukturen und der Syntax von Python jonglieren muss. Ich würde mich schrittweise da herantasten. Hier mal als Anregung ein ähnliches Beispiel :

Code: Alles auswählen

In [1]: numbers = { 1: 'Eins', 2: 'Zwei', 3: 'Drei'}

In [2]: dict(map(lambda x: (x[1], x[0]), numbers.items()))
Out[2]: {'Drei': 3, 'Eins': 1, 'Zwei': 2}
(Eigentlich ist das schon fast eine Lösung ;) )
Nö, finde ich nicht schön. Die Syntax ist als sie eingeführt wurde nicht wirklich nötig gewesen weil sie kein Problem gelöst hat. Schreib `dict` vor die geschweifte Klammer, mach aus den geschweiften Klammern runde Klammern, und aus dem ``schlüssel: wert``-Teil ein Tupel ``(schlüssel, wert)`` und Du hast den gleichen Effekt mit weniger zusätzlicher Syntax.
Ich kann den Punkt mit der zusätzlichen Syntax zwar irgendwie nachvollziehen, und aus zugehörigen dem PEP geht hervor, dass sie lange nicht umgesetzt wurden, weil es dict und Generatoren gibt. Nur könnte man mit der Begründung nicht alle Comprehensions durch Generatoren ersetzen? Set- und Listcomprehensions finde ich persönlich ganz nett, Dicionaries wirken ein bisschen so, als wären sie in erster Linie da, weil es die anderen beiden gibt. Teilweise scheint es ja auch um Performancegründe zu gehen.
Ambriador
User
Beiträge: 35
Registriert: Freitag 25. November 2016, 01:05

Leider bin ich jetzt noch mehr verwirrt :oops:
Ich hab keine Ahnung wie ich innerhalb von map(lambda) überhaupt die beiden Listen bearbeiten soll um eine Liste bzw ein dict wieder zu bekommen?
Benutzeravatar
pyHoax
User
Beiträge: 84
Registriert: Donnerstag 15. Dezember 2016, 19:17

Ambriador hat geschrieben:Leider bin ich jetzt noch mehr verwirrt :oops:
Ich hab keine Ahnung wie ich innerhalb von map(lambda) überhaupt die beiden Listen bearbeiten soll um eine Liste bzw ein dict wieder zu bekommen?
Ja nicht war ?
Anstatt der Dict-comprehension (siehe) oben hätten sie sich lambda Ausdrücke spaaren können.

Die Lösung die du suchst ist das hier:

Code: Alles auswählen

 dict(map(lambda (matrikel, note): (matrikel, note_zahl_zu_string[note]), matrikelnummer_zu_note.items()))
Gräßlich oder ?

Hier nochmal mein Liebling :

Code: Alles auswählen

{ matrikelnummer: note_zahl_zu_string[note] for matrikelnummer, note in matrikelnummer_zu_note.items() }
Ambriador
User
Beiträge: 35
Registriert: Freitag 25. November 2016, 01:05

Jetzt wo man es sieht ist es einleuchtend, aber so ohne weiteres wär ich da echt nicht drauf gekommen, map() und lambda bereiten mir echt Kopfschmerzen :D
Allerdings sagt er mir jetzt

Code: Alles auswählen

matrikel_zu_noten_string = dict(map(lambda (matrikel,note): (matrikel, note_zahl_zu_string[note]), matrikelnummer_zu_note.items()))
                                               ^
SyntaxError: invalid syntax
Der Pfeil zeigt dabei auf die Klammer "(matrikel,note)". Liegt wohl an Python 2.x, aber wie formt man das um? Aus der https://www.python.org/dev/peps/pep-3113/ Anleitung werde ich auch nicht schlau.
Benutzeravatar
pyHoax
User
Beiträge: 84
Registriert: Donnerstag 15. Dezember 2016, 19:17

Hmmden PEP werd ich lesen, finnd ich nicht so prickelnd..

Aber du findest doch im Pep sogar die Umformungsregel...

dict(map(lambda matrikel_note: (matrikel_note[0], note_zahl_zu_string[matrikel_note[1]]), matrikelnummer_zu_note.items()))
Ambriador
User
Beiträge: 35
Registriert: Freitag 25. November 2016, 01:05

Vielen Dank, die Aufgabe hat mir echt zu schaffen gemacht :)
BlackJack

@nezzcarth: Mit der Begründung könnte man in der Tat alle „comprehensions“ ersetzen, und ich persönlich hätte da auch gar nichts gegen. Die „list comprehensions“ war recht lange vor den Generatorausdrücken in der Sprache. Ich denke wenn dem nicht so wäre, dann wäre sie, und die ganzen anderen Varianten, wahrscheinlich nicht in der Sprache gelandet.

@pyHoax: Natürlich ist die Lösung mit `map()` und ``lambda`` grässlich, das will ja aber auch niemand ernsthaft.

Code: Alles auswählen

dict((matrikelnummer, note_zahl_zu_string[note]) for matrikelnummer, note in matrikelnummer_zu_note.items())
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@BlackJack: Vielleicht hätte man gleich for-Comprehensions a la Scala einführen sollen... Monadic Python... mjam... :twisted:
In specifications, Murphy's Law supersedes Ohm's.
Antworten