@mali321: `defaultdict` kannst Du verwenden wenn die Reihenfolge der Ergebnisse nicht zwingend erhalten bleiben muss. Allerdings macht die letzte ``for``-Schleife keinen Sinn. Was denkst Du denn was ``for d[k] in d:`` bedeutet? Und *in* der Schleife ist `d.values()` sicher nicht das was Du denkst was es ist, denn die Elemente haben keine `replace()`-Methode.
Es kann auch sein, dass es Dir einfacher fallen würde wenn die Namen nicht fast durchgehend schlecht gewählt sind. Nichtssagende Namen wie `liste` oder gar einbuchstabige Namen helfen nicht beim Verständnis was für Werte das sind und welche Bedeutung die im Programm haben. Auch sollten Grunddatentypen nicht Bestandteil von Namen sein. Bei `neue_liste_mapping` ist `liste` auch falsch, denn `zip()` liefert als Ergebnis keine Liste. Auch der Präfix `neue_` bei den Namen macht nicht wirklich sinn, denn irgendwie ist ja jedes Objekt das man erstellt Neu, so ein Namenszusatz macht also nur Sinn wenn man auch eine ”alte” Liste mit gleichartigen Werten hat gegen die man die neue Liste abgrenzen möchte.
Aber mal von oben angefangen: Beim öffnen der CSV-Datei fehlt die Angabe der verwendeten Kodierung und das `newline`-Argument wie in der Dokumentation vom `csv`-Modul gefordert. Das kann so funktionieren, muss es aber nicht.
`datei` ist ein schlechter Name für ein CSV-Reader-Objekt weil das keine Datei ist, und dementsprechend auch nicht die Methoden bietet, die man von einem Dateiobjekt erwartet. Wenn man das beispielsweise `rows` nennt, kann man `einzulesende_datei` dafür einfach nur `datei` nennen. In den zwei direkt aufeinander folgenden Zeilen wo dieser Name verwendet wird, sieht man ja sehr leicht, dass die Datei zum lesen geöffnet wurde, auch ohne dass das im Namen steht.
Alle Datensätze erst in eine Liste einzuslesen um dann die Kopfzeile mit ``pop(0)`` zu entfernen ist ineffizient, sowohl was den Speicherverbrauch angeht, als auch von der Laufzeit. Man würde hier einfach die Kopfzeile direkt aus dem Reader-Objekt mit `next()` überspringen.
Es macht keinen Sinn `neue_liste_mapping` in jedem Schleifendurchlauf erneut zu erstellen und am Ende nur den letzten zugewiesenen Wert zu verwenden. Was auch zusätzlich noch die Gefahr birgt, dass bei leerer Eingabedatei dieser Name gänzlich undefiniert bleibt und der Code danach unweigerlich in eine Ausnahme läuft.
Aber es macht eigentlich auch gar keinen Sinn erst die Artikelnummern in einer und die Mengen in eine zweite Liste zu stecken, nur um die dann gleich danach mit `zip()` zusammenzuführen. Man könnte da gleich eine Liste mit Paaren erstellen.
Und auch die kann man sich sparen wenn die dann nur wieder in einer weiteren Schleife verwendet wird um die ganzen Werte in ein `defaultdict` zu stecken.
Und auch das `defaultdict` das Artikelnummer auf Mengen abbildet ist zu umständlich wenn im nächsten Schritt dann die Mengen pro Artikelnummer aufsummiert werden. Das aufsummieren hätte man ja auch *geich* machen können, statt da erst Listen pro Artikelnummer aufzubauen.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
import csv
from collections import defaultdict
def main():
with open(
R"C:\Users\nobody\Desktop\x.csv", encoding="ascii", newline=""
) as datei:
rows = csv.reader(datei, delimiter=";")
next(rows) # Skip header.
article_number_to_amount = defaultdict(float)
for article_number, *_, amount_text in rows:
article_number_to_amount[article_number] += float(
amount_text.replace(",", ".")
)
for article_number, amount in article_number_to_amount.items():
print(f"{article_number}: {amount:.3f}")
if __name__ == "__main__":
main()
Wobei das nicht die Speichereffizienteste Lösung ist erst ein Wörterbuch aufzubauen und es dann auszugeben, denn eigentlich braucht man ja nur die Summe für die aktuell bearbeitete Artikelnummer und wenn man die fertig berechnet und ausgegeben hat, kann man sowohl Artikelnummer als auch Summe wieder ”vergessen”. Das wäre dann eine Lösung mit `itertools.groupby()`.