簡體   English   中英

Python 數據類到列表字典

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM