Seite 1 von 1

Elemente eine Liste neu anordnen

Verfasst: Dienstag 30. August 2022, 12:56
von fr01u
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!!!

Re: Elemente eine Liste neu anordnen

Verfasst: Dienstag 30. August 2022, 17:02
von __blackjack__
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.

Re: Elemente eine Liste neu anordnen

Verfasst: Dienstag 30. August 2022, 17:12
von fr01u
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!

Re: Elemente eine Liste neu anordnen

Verfasst: Dienstag 30. August 2022, 17:50
von __blackjack__
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]]