Seite 1 von 1

Liste von Dictionaries in Liste von Dataklassen

Verfasst: Sonntag 3. Oktober 2021, 12:21
von rogerb
Hallo zusammen,

ich möchte eine Liste von Dictionaries in einer Liste von Klasseninstanzen konvertieren.
Leider habe ich keinen Einfluss auf die Struktur der Eingangsdaten.

Ich habe diese etwas umständliche Lösung gefunden (generisches Beispiel):

Code: Alles auswählen

from dataclasses import dataclass

@dataclass
class Item:
    key: str
    value: str


data = [
    {"key1": "value1"},
    {"key2": "value2"},
    {"key3": "value3"},
]


items = [Item(*next((key,value) for key, value in item.items())) for item in data]
Daher die Frage: Kennt jemand eine Möglichkeit das eleganter zu lösen?

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Sonntag 3. Oktober 2021, 12:31
von Sirius3
Ich wundere mich, wie da die innere for-Schleife herkommt?

Code: Alles auswählen

items = [Item(*next(item.items())) for item in data]

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Sonntag 3. Oktober 2021, 14:31
von rogerb
Sirius3 hat geschrieben: Sonntag 3. Oktober 2021, 12:31 Ich wundere mich, wie da die innere for-Schleife herkommt?
Weil es sonst eine Exception gibt:
'dict_items' object is not an iterator

Ohne innere Schleife ginge das auch noch:

Code: Alles auswählen

items = [Item(*next(iter(item.items()))) for item in data]
Das sieht immer noch umständlich aus.

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Sonntag 3. Oktober 2021, 15:38
von Sirius3
Ja, das ist auch nicht schön. Vielleicht so:

Code: Alles auswählen

[Item(key, value) for item in data for key, value in item.items()]

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Sonntag 3. Oktober 2021, 15:51
von rogerb
Ja, Danke! Ist wahrscheinlich die beste Lösung, so.

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Montag 4. Oktober 2021, 05:22
von LukeNukem
rogerb hat geschrieben: Sonntag 3. Oktober 2021, 15:51 Ja, Danke! Ist wahrscheinlich die beste Lösung, so.
Ach, ich weiß nicht...

Code: Alles auswählen

[Item(*(d.popitem())) for d in data]
Nur so 'ne Idee. ;-)

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Montag 4. Oktober 2021, 07:36
von rogerb
@LukeNukem,

Danke für den Vorschlag. Das ist zwar möglich, wegen des destruktiven Verhaltens, (in diesem Fall) aber nicht anwendbar.

Mal abgesehen davon, ... Ich weiß zwar nicht seit wann es pop() in Python gibt, aber ich kann mir eigentlich nur vorstellen, dass es von Anfang an drin war. Denn als "Sprachverbesserung" wäre es wahrscheinlich immer abgeschmettert worden.
Kennt jemand die Geschichte? Wie findet man eigentlich am schnellsten heraus, wann was zu Python hinzugefügt wurde, ohne sich durch alle Releasenotes lesen zu müssen?

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Montag 4. Oktober 2021, 09:14
von Sirius3
@rogerb: bei Dingen, die nicht "schon immer" da waren, findet man in der Dokumentation den Hinweis, ab welcher Version z.B. eine Funktion existiert.
Bei popitem steht die Begründung gleich mit dabei, da sich wohl so manche (wie Du) gefragt haben dürfte, warum es das gibt.

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Montag 4. Oktober 2021, 14:28
von DeaD_EyE
Das ist nur doof, wenn man anfängt ein dict zu verändern, wenn man es an anderer Stelle ggf. noch benötigt.

So würde ich es machen:

Code: Alles auswählen

from dataclasses import dataclass


@dataclass
class Item:
    key: str
    value: str

    @classmethod
    def from_mapping(cls, mapping):
        return cls(*mapping.copy().popitem())


data = [
    {"key1": "value1"},
    {"key2": "value2"},
    {"key3": "value3"},
]


data2 = [Item.from_mapping(mapping) for mapping in data]

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Montag 4. Oktober 2021, 15:04
von Sirius3
Wenn man schon eine eigene Methode hat, dann ist man ja nicht mehr auf eine Anweisung beschränkt und kann viel verständlicher schreiben:

Code: Alles auswählen

@dataclass
class Item:
    key: str
    value: str

    @classmethod
    def from_mapping(cls, mapping):
        ((key, value), ) = mapping.items()
        return cls(key, value)

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Sonntag 10. Oktober 2021, 09:09
von DeaD_EyE
Das ist aber auch nicht viel besser :-D
Bei deinem Code kommt es zu einer Exception, wenn das Dict mehr als ein Key-Value paar hat. Bei meinem Code wird das letzte hinzugefügte Key-Value-Paar ausgegeben, egal wie viele Keys enthalten sind.

Wenn du das so nachbauen willst:

Code: Alles auswählen

@dataclass
class Item:
    key: str
    value: str

    @classmethod
    def from_mapping(cls, mapping):
        *_, (key, value) = mapping.items()
        return cls(key, value)

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Sonntag 10. Oktober 2021, 11:44
von Sirius3
Ich würde behaupten, das ist ein Vorteil. Bei mehr als einem Key macht die Dataklasse keinen Sinn.

Re: Liste von Dictionaries in Liste von Dataklassen

Verfasst: Sonntag 10. Oktober 2021, 12:13
von rogerb
Sirius3 hat geschrieben: Sonntag 10. Oktober 2021, 11:44 Ich würde behaupten, das ist ein Vorteil. Bei mehr als einem Key macht die Dataklasse keinen Sinn.
Einmal das und außerdem ist die ursprüngliche Datenstruktur ja dummerweise eine Liste in der jedes Element aus jeweils nur einem Key-Value-Pair besteht.