[英]Python dataclass to dictionary of lists
從數據類列表(或包含列表的數據類 B)中:
import dataclasses
from typing import List
@dataclasses.dataclass
class A:
a: str
b: int
@dataclasses.dataclass
class B:
l: List[A]
da = B([A("a", 3), A("b", 4)])
# or
da = [A("a", 3), A("b", 4)]
我想得到一個列表字典:
# {'a': ['a', 'b'], 'b': [3, 4]}
我發現的唯一方法是使用丑陋的循環:
from collections import defaultdict
res = defaultdict(list)
for item in da:
for field in dataclasses.fields(item):
res[field.name].append(getattr(item, field.name))
print(res) # defaultdict(<class 'list'>, {'a': ['a', 'b'], 'b': [3, 4]})
似乎是一件很簡單的事情,必須有一個更簡單的方法和更多的 Pythonic。
丑陋的循環實際上並沒有那么糟糕。 如果你想讓它成為一個單線,使用functools.reduce
:
import dataclasses
from collections import defaultdict
from functools import reduce
from typing import Any, List, Protocol, Sequence, cast
@dataclasses.dataclass
class A:
a: str
b: int
@dataclasses.dataclass
class B:
l: List[A]
class Dataclass(Protocol):
__dataclass_fields__: dict[str, Any]
def to_dict_of_lists(_dataclasses: Sequence[Dataclass]) -> dict[str, list[Any]]:
return reduce(
lambda acc, x: {field.name: acc[field.name] + [getattr(x, field.name)] for field in dataclasses.fields(x)},
_dataclasses,
cast(dict[str, list[Any]], defaultdict(list)),
)
da = [A("a", 3), A("b", 4)]
print(to_dict_of_lists(da)) # {'a': ['a', 'b'], 'b': [3, 4]}
免責聲明:與簡單循環相比,這效率低且可讀性差。 把它當作一個有趣的事實。
還有其他一些方法可以做到這一點,但所有這些方法都是關於迭代值列表。 您對此結果的解決方案非常好。
dataclasses.asdict
可能會對您有所幫助,但您無法避免遍歷列表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.