按对象的属性对对象字典进行排序

发布于 2025-01-13 08:12:16 字数 474 浏览 1 评论 0原文

一个字典有一个键,它的值是一个带有属性的类的对象

dic = { 1:Person("John, Greenberg", 3), 
        2:Person("Thomas, San", 5), 
        3:Person("Annie, Dawn", 7) }


class Person:
    def __init__(self, name, total_hour):
         self.name = name
         self.total_hour = total_hour

如何按对象的属性“名称”对字典进行排序?

预期输出:

dic = { 3:Person("Annie, Dawn", 7), 
        1:Person("John, Greenberg", 3), 
        2:Person("Thomas, San", 5) }

A dictionary that has a key, the value it is a object of class with attributes

dic = { 1:Person("John, Greenberg", 3), 
        2:Person("Thomas, San", 5), 
        3:Person("Annie, Dawn", 7) }


class Person:
    def __init__(self, name, total_hour):
         self.name = name
         self.total_hour = total_hour

How to sort the dictionary by the object's attribute 'name'?

Expected output:

dic = { 3:Person("Annie, Dawn", 7), 
        1:Person("John, Greenberg", 3), 
        2:Person("Thomas, San", 5) }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

莫多说 2025-01-20 08:12:16

对字典进行“排序”并使其所有键都是数字,这有点“味道”,表明您使用了错误的数据结构 - 您确定不想保留这些 Person在列表而不是字典中?

也就是说,您可以通过对 Python 中的 items() 进行排序,然后使用排序后的项目重新创建一个新的字典来对 Python 中的字典(从版本 3.7 开始)进行“排序”,因为字典会保留插入顺序它的键:

>>> class Person:
...     def __init__(self, name, total_hour):
...          self.name = name
...          self.total_hour = total_hour
...
>>> dic = { 1:Person("John, Greenberg", 3),
...         2:Person("Thomas, San", 5),
...         3:Person("Annie, Dawn", 7) }
>>> dict(sorted(dic.items(), key=lambda i: i[1].name))
{3: <__main__.Person object at 0x00000239E799AE90>, 1: <__main__.Person object at 0x00000239E7999FF0>, 2: <__main__.Person object at 0x00000239E799AE30>}

"Sorting" a dictionary and having all its keys be numbers are sort of a "smell" that you're using the wrong data structure -- are you sure you don't want to keep these Persons in a list rather than a dict?

That said, you can "sort" a dict in Python (as of version 3.7) by sorting its items() and then using the sorted items to recreate a fresh dict, since a dict preserves the insertion order of its keys:

>>> class Person:
...     def __init__(self, name, total_hour):
...          self.name = name
...          self.total_hour = total_hour
...
>>> dic = { 1:Person("John, Greenberg", 3),
...         2:Person("Thomas, San", 5),
...         3:Person("Annie, Dawn", 7) }
>>> dict(sorted(dic.items(), key=lambda i: i[1].name))
{3: <__main__.Person object at 0x00000239E799AE90>, 1: <__main__.Person object at 0x00000239E7999FF0>, 2: <__main__.Person object at 0x00000239E799AE30>}
你的笑 2025-01-20 08:12:16

正如您在看到标记为 sorteddictionary 的其他问题时可能注意到的那样,sortedcollections 有一个 ValueSortedDict 类型。
如果您只想对字典进行一次排序,Samwise 上面的答案是完全可用的(对于 Python 3.7+,否则使用 collections.OrderedDict 来保存排序值)。但是,如果您希望字典在添加更多元素时保持排序,则 ValueSortedDict 是最佳选择。

使 person 类中的对象能够按属性排序的一个好方法是添加比较魔术方法(__eq____le____ge__ 和等等)到你的班级,或者使用 dataclasses.dataclass 启用比较您的对象的一个​​或多个属性。

>>> import dataclasses
>>> from sortedcollections import ValueSortedDict
>>> @dataclasses.dataclass(order=True)
... class Person:
...     name: str # by default, this is factored into the sort order
...     total_hour: int = dataclasses.field(compare=False) # disable sorting by total_hour
...
>>> dic = { 1:Person("John, Greenberg", 3),
...     2:Person("Thomas, San", 5),
...     3:Person("Annie, Dawn", 7) }
>>> sdic = ValueSortedDict(dic)
>>> sdic
ValueSortedDict(None, {3: Person(name='Annie, Dawn', total_hour=7), 1: Person(name='John, Greenberg', total_hour=3), 2: Person(name='Thomas, San', total_hour=5)})
>>> sdic[4] = Person('Bezos, Jeff', 6)
>>> sdic
ValueSortedDict(None, {3: Person(name='Annie, Dawn', total_hour=7), 4: Person(name='Bezos, Jeff', total_hour=6), 1: Person(name='John, Greenberg', total_hour=3), 2: Person(name='Thomas, San', total_hour=5)})

As you may note from seeing other questions tagged sorteddictionary, sortedcollections has a ValueSortedDict type.
If you only want to sort the dict once, Samwise's answer above is perfectly serviceable (for Python 3.7+, otherwise use a collections.OrderedDict to hold your sorted values). But if you want your dict to stay sorted as you add more elements, a ValueSortedDict is the way to go.

A good way to enable objects in your person class to be sorted by their attributes is to add comparison magic methods (__eq__, __le__, __ge__ and so forth) to your class, or use a dataclasses.dataclass to enable comparison of your objects by one or more attributes.

>>> import dataclasses
>>> from sortedcollections import ValueSortedDict
>>> @dataclasses.dataclass(order=True)
... class Person:
...     name: str # by default, this is factored into the sort order
...     total_hour: int = dataclasses.field(compare=False) # disable sorting by total_hour
...
>>> dic = { 1:Person("John, Greenberg", 3),
...     2:Person("Thomas, San", 5),
...     3:Person("Annie, Dawn", 7) }
>>> sdic = ValueSortedDict(dic)
>>> sdic
ValueSortedDict(None, {3: Person(name='Annie, Dawn', total_hour=7), 1: Person(name='John, Greenberg', total_hour=3), 2: Person(name='Thomas, San', total_hour=5)})
>>> sdic[4] = Person('Bezos, Jeff', 6)
>>> sdic
ValueSortedDict(None, {3: Person(name='Annie, Dawn', total_hour=7), 4: Person(name='Bezos, Jeff', total_hour=6), 1: Person(name='John, Greenberg', total_hour=3), 2: Person(name='Thomas, San', total_hour=5)})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文