Elemente eine Liste neu anordnen

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
fr01u
User
Beiträge: 2
Registriert: Dienstag 30. August 2022, 12:25

Hallo miteinander,
vor folgender Herausforderung stehe ich:
Von einer Datenbankabfrage bekomme ich Umsatzzahlen pro Jahr und Monat zurück. Die Ergebnisliste ist wie folgt aufgebaut:
[('2021', '1', -23), ('2021', '2', -24), ('2021', '3', -25), ('2021', '4', -26), ('2022', '1', -31), ('2022', '02', -32), ('2022', '3', -33), ('2022', '5', -34)]
Für die Darstellung der Werte in einer Table-Maske (pysimplegui) brauche ich aber eine Tabelle bei der in der x-Ache die Monate aufgeführt sind und in der y-Ache das Jahr steht.
Beispiel:

Jahr Jan Feb Mrz Apr Mai Jun Jul ... ...
2021 -23 -24 -25 -26 0 0 -30
2022 -31 -32 -33 0 -34 0 0

Die "Input-Liste" für die pysimlegui-Table bräuchte also das folgende Format:
input_liste = [('2021', -23, -24, -25, -26, 0, 0, -30 ... ...), ('2022', -31, -32, -33, 0, -34, 0, 0, ....)]

Wie bekomme ich diese "Umformung" am elegantesten hin?
Ich "verliere" mich immer wieder in geschachtelten FOR-Schleifen :shock:
Schon mal vielen Dank für Eure Bemühungen!!!
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Warum sind denn Jahr und Monat Zeichenketten und keine Zahlen? Kann man davon ausgehen, dass die Monate trotzdem numerisch sortiert vorliegen? Und das die Daten vollständig sind, und nicht mal Monate fehlen können? Sind die Daten in der Datenbank wenigstens konsistent und nicht mal "2" und mal "02" für den Februar, wie in den Beispieldaten? Falls die Daten vollständig und in der richtigen Reihenfolge sind:

Code: Alles auswählen

In [34]: data                                                                   
Out[34]: 
[('2021', '1', -23),
 ('2021', '2', -24),
 ('2021', '3', -25),
 ('2021', '4', -26),
 ('2022', '1', -31),
 ('2022', '02', -32),
 ('2022', '3', -33),
 ('2022', '5', -34)]

In [35]: from itertools import groupby                                          

In [36]: from operator import itemgetter                                        

In [37]: [[year, *map(itemgetter(2), group)] for year, group in groupby(data, itemgetter(0))]                                                          
Out[37]: [['2021', -23, -24, -25, -26], ['2022', -31, -32, -33, -34]]
Ansonsten ist etwas mehr Aufwand nötig. Da würde ich empfehlen das Problem in kleinere Teilprobleme zu zerlegen und in jeweils einer kurzen Funktion pro Teilproblem zu lösen, statt sich da zu viele verschachtelte Schleifen auf einmal einzufangen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
fr01u
User
Beiträge: 2
Registriert: Dienstag 30. August 2022, 12:25

Super, vielen Dank für die schnelle Antwort. Leider sind die "Rohdaten", was die Monate angeht, nicht immer vollständig. Es kann also sein, dass bei einigen Monaten keine Umsatzzahlen vorhanden sind. Zwischenzeitlich bin ich so vorgegangen wie Du gesagt hast, den "Elefanten" in Scheiben geschnitten und verspeist :D . Also ich hab es jetzt am laufen. Die beiden Bibliotheken "itertools" und "operator" sind neu für mich, die werde ich mir mal anschauen.
Aber auf alle Fälle vielen Dank für Deine Unterstützung!
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Zum auffüllen der Monate könnte man ein `defaultdict` dazwischen schalten, dann ist nur noch die Sortierung nach Jahr wichtig, nicht mehr die nach Monaten und deren Vollständigkeit:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import defaultdict
from itertools import groupby
from operator import itemgetter
from pprint import pprint


def main():
    data = [
        ("2021", "1", -23),
        ("2021", "2", -24),
        ("2021", "3", -25),
        ("2021", "4", -26),
        ("2022", "1", -31),
        ("2022", "02", -32),
        ("2022", "3", -33),
        ("2022", "5", -34),
    ]
    table = []
    for year, group in groupby(data, itemgetter(0)):
        month_to_value = defaultdict(
            int, ((int(month_text), value) for _, month_text, value in group)
        )
        table.append(
            [year, *(month_to_value[month] for month in range(1, 13))]
        )
    pprint(table)


if __name__ == "__main__":
    main()
Ausgabe:

Code: Alles auswählen

$ python3.6 test2.py
[['2021', -23, -24, -25, -26, 0, 0, 0, 0, 0, 0, 0, 0],
 ['2022', -31, -32, -33, 0, -34, 0, 0, 0, 0, 0, 0, 0]]
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten