Summe aus 2 Dictionaries

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
elguapo
User
Beiträge: 2
Registriert: Dienstag 10. November 2020, 11:05

Hallo erstmal,
ich bin hier neu und auch in python ein Neuling. Ich habe einige Daten in Python zusammengefügt und berechnet. Nun stosse ich aber an meine laienhaften Grenzen. Ich habe u.a. ein Dictionary mit key(s) und dann als value eine Liste. In dieser ist die Niederlassung der Pkws vermerkt. Ich möchte nun über ein 2 Dictionary eine Summe der Autos ausgeben die in Niederlassung 1 und 2 sind. Dabei interessiert mich die Marke nicht, sondern nur die Niederlassung. Der zuberechnende Wert in der Liste wäre die Summe aus Eintrag [-2], also die Zahlen und die Referenz [-1] also die Niederlassung.

auto = {
"bmw": ["blau", "automatik", 5, "nl_01"],
"audi": ["rot", "manuell", 4, "nl_02"],
"smart": ["blau", "automatik", 2, "nl_01"],
"audi": ["blau", "manuell", 5, "nl_01"],
"opel": ["blau", "automatik", 1, "nl_02"],
}

niederlassung = {
"nl_01": "Bremen",
"nl_02": "Hamburg",
}

Ergebnis soll sein:
Bremen = 12
Hamburg = 5

Vielen Dank schon mal.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@elguapo: Das Ergebnis ist eine Ausgabe nehme ich mal an. Was ist denn jetzt das konkrete Problem? Du hast Werte/Datenstrukturen gegeben, und eine Ausgabe zu der Du hin willst. Jetzt musst Du, ähnlich wie in der Mathematik, einen Weg finden von dem was gegeben ist, zu dem was gesucht ist zu kommen. Über gegebenfalls über Zwischenergebnisse. Wie sähe denn beispielsweise eine Datenstruktur aus die das gesuchte Ergebnis darstellen würde? Die nächste Frage ist dann wie man die aus den gegebenen Daten aufbauen könnte.

Tipp für Datentyp: `collections.defaultdict`. Dann spart man sich Code den man für ein `dict` sonst selbst schreiben müsste. Wobei das mit der `get()`-Methode, wenn man sich da mal alle Argumente anschaut, auch nicht wirklich kompliziert ist.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Das obere Dictionary ist falsch, so kann man die Aufgabe nicht lösen. Keys sollten einzigartig sein, zwei mal der selbe Key in einem Dict geht nicht.


Ich würde da so vorgehen:

bremen auf 0 setzen
hamburg auf 0 setzen
Eine Schleife über niederlassung_key, niederlassung_value von niederlassung.
Eine Schleife über auto_key, auto_value von auto.
Wenn niederlassung_value gleich "Bremen" ist und der dritte Wert von auto_value gleich dem niederlassung_key ist, wird der zweite Wert von auto_value auf bremen addiert.
Wenn niederlassung_value gleich "Hamburg" ist un der dritte Wert von auto_value gleich dem niederlassung_key ist, wird der zweite Wert von auto_value auf hamburg addiert.
Dann am Ende werden beide Werte (hamburg, bremen) ausgegeben.
elguapo
User
Beiträge: 2
Registriert: Dienstag 10. November 2020, 11:05

@jankie:
du hast vollkommen recht: 2x audi geht nicht, muss halt ford sein. grundsätzlich komme ich aber nicht weiter.

@__blackjack__: ersteinmal danke für deine antwort.
das obige ergebnis ist was rauskommen soll. ich denke es geht mit einer funktion.
bsp.:

def niederlassung(auto: dict, niederlassung: dict):
result_nl = {}
for key in niederlassung:
if key in auto.keys():
niederlassung[key] = sum(auto[-1]) """==> das ist wohl falsch; ich möchte eine Summe pro Niederlassung, dh. Summe auf letzten Wert der Liste im Dictionary auto über den Referenzwert nl_01 und nl_02 (letzter Eintrag in Dict auto) und diesen dann übergeben""""
result_nl = niederlassung
return result_nl

"""Das Ergebnis wäre dann"""
result_nl = {
nl_01: 12,
nl_02: 5,
}

Danke elguapo
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@elguapo: Lass mal diese unsinnigen Typannotationen weg oder mach sie wirklich ordentlich und vollständig. Und was verwendest Du zum prüfen der Typannotationen? Wenn man die nämlich nicht prüft ist das sogar ein Stück weit gefährlich die zu machen, denn die machen ja ein deutlich stärkeres Versprechen als Kommentare oder Dokumentation. Der Leser verlässt sich darauf, das die Angaben dort automatisiert statisch überprüft wurden.

Literale Zeichenketten sind keine Kommentare. Das Kommentarzeichen ist #, nichts anderes.

Und ja es ist falsch eine einfache Zuweisung zu machen wenn man eigentlich etwas aufsummieren will. Der Operator dafür ist ``+``.

`key` ist eine Niederlassungs-ID. Die ist niemals in den Schlüsseln von `auto`, denn das sind ja Automarken.

Am Anfang der Funktion wird `result_nl` als leeres Wörterbuch definiert. Das wird dann aber nirgends verwendet. Sollte es aber wohl, denn da soll ja am Ende das Ergebnis drin stehen.

Wohingegen es überhaupt keine gute Idee ist eines der Argumente zu verändern, und dann auch noch andere Informationen dort zu speichern als das ursprünglich enthalten waren. Du würdest bei `niederlassung` ja die Werte überschreiben, und wie soll man dann von der Niederlassungs-ID zum Namen der Stadt kommen wenn die Städtenamen durch Zahlen ersetzt wurden? Funktionen sollten in der Regel ihre Argumente nicht verändern sondern neue Werte/Datenstrukturen erstellen und als Rückgabewert liefern.

Namen: `auto` und `niederlassung` sind schlechte weil unpassende Namen. `auto` beschreibt nicht *ein* Auto. Um Grunde nicht einmal mehrere Autos, sondern den Warenbestand pro Automarke für alle Niederlassungen. Und letztendlich haben wir durch die Doppelung beim "audi" auch gesehen, das die Datenstruktur nicht funktioniert. Man kann damit nicht die gleiche Automarke in mehr als einer Niederlassung haben, oder mit unterschiedlichen Werten für die Gangschaltung in der gleichen Niederlassung. Mit dieser Datenstruktur lassen sich die realen Daten überhaupt nicht abbilden.

`niederlassung` beschreibt keine Niederlassung, sondern ist eine Abbildung von Niederlassungs-ID auf einen Städte- oder Ländernamen. Kann man bei den beiden Beispielwerten nicht genauer erkennen, denn beides sind ja gleichzeitig Stadt und Bundesland.

`result_nl` ist ein schlechter Name weil er eine kryptische Abkürzung enthält.

Und `niederlassung()` ist ein schlechter Name für eine Funktion weil der keine Tätigkeit beschreibt. Funktions- und Methodennamen beschreiben üblicherweise die Tätigkeit die von dem Code durchgeführt wird, um sie von eher passiven Werten unterscheiden zu können. Der Name `niederlassung` wird hier auch mehrfach belegt, einmal als Datenstruktur und dann als Funktion, und auch noch als Argumentname in dieser Funktion. Das ist sehr verwirrend.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Wie du da grundsätzlich vorgehen kannst habe ich doch schon geschreiben. Versuch das doch mal umzusetzen. Wenn du das dann hast kannst du das auch in eine Funktion packen oder die Ergebnisausgabe als Dictionary versuchen.

Oder du versuchst es wie von __blackjack__ beschrieben.
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

@Jankie: warum sollte man zwei Schleifen schreiben? Dafür hast Du doch ein Wörterbuch über die Niederlassungen.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Stimmt, hab das ganze noch mal überarbeitet.

Code: Alles auswählen

from collections import defaultdict

CARBRAND_TO_STOCK_CARS = {
    "bmw": ["blau", "automatik", 5, "nl_01"],
    "benz": ["rot", "manuell", 4, "nl_02"],
    "smart": ["blau", "automatik", 2, "nl_01"],
    "audi": ["blau", "manuell", 5, "nl_01"],
    "opel": ["blau", "automatik", 1, "nl_02"],
}

BRANCH_ID_TO_CITYNAME = {
    "nl_01": "Bremen",
    "nl_02": "Hamburg",
}

def main():
    result = defaultdict(int)
    for carbrand_value in CARBRAND_TO_STOCK_CARS.values():
        result[BRANCH_ID_TO_CITYNAME.get(carbrand_value[3])] += carbrand_value[2]
    print(result)

if __name__ == "__main__":
    main()
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

@Jankie: `carbrand_value` solltest Du gleich in 4 Variablen entpacken.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Damit die Lesbarkeit erhöht wird?

Würde man dann eher alle entpacken und zwei einfach nicht verwenden, also so:

Code: Alles auswählen

def main():
    result = defaultdict(int)
    for carbrand_value in CARBRAND_TO_STOCK_CARS.values():
        car_color, transmission_type, number_of_cars, car_branch = carbrand_value
        result[BRANCH_ID_TO_CITYNAME.get(car_branch)] += number_of_cars
    print(result)
oder würde man die Liste slicen und nur die letzten zwei Elemente verwenden?

Code: Alles auswählen

def main():
    result = defaultdict(int)
    for carbrand_value in CARBRAND_TO_STOCK_CARS.values():
        number_of_cars, car_branch = carbrand_value[-2:]
        result[BRANCH_ID_TO_CITYNAME.get(car_branch)] += number_of_cars
    print(result)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Man entpackt ungebrauchte Elemente in den _

Code: Alles auswählen

for a, b, _, _ in ...
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

Man entpackt schon im for:

Code: Alles auswählen

def main():
    result = defaultdict(int)
    for _, _, number_of_cars, car_branch in CARBRAND_TO_STOCK_CARS.values():
        result[BRANCH_ID_TO_CITYNAME.get(car_branch)] += number_of_cars
    print(result)
Antworten