Python sort方法参数采用相同的preden

2024-05-19 09:33:39 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的程序中,我想按姓名排序所有联系人,先按姓氏排序,然后按名字排序。你知道吗

我有一个代码可以帮我做这件事,但它并不是我想要的那样。你知道吗

例如,如果我有一个按当前代码排序的名称列表,它将如下所示:

Luke
Riyaan
Amanda Benson

如您所见,代码仍然将None作为要排序的值,我想要的是:

Amanda Benson
Luke
Riyaan

因此,基本上,如果姓氏返回None,那么我希望程序对名字进行排序,使其与具有姓氏的对象具有相同的优先级。你知道吗

下面是我当前用于排序名称的代码:

import operator

...

addressBook = AddressBook()
addressBook.contactsList
addressBook.contactsList.sort(key = operator.attrgetter("lastName", "firstName"))

Tags: 代码程序名称none排序名字operator姓名
2条回答

最好的方法是在(我猜)类Contact中实现the rich comparison magic methods

class Contact(object):

    def __init__(self, first_name, last_name=""):
        self.first_name = first_name
        self.last_name = last_name

    def __repr__(self): # to make the demo clearer!
        if not self.last_name:
            return str(self.first_name)
        return "{0.first_name} {0.last_name}".format(self)

    def __eq__(self, other):
        return (self.first_name == other.first_name and 
                self.last_name == other.last_name)

    def __lt__(self, other):
        if self.last_name and other.last_name:
            if self.last_name == other.last_name:
                return self.first_name < other.first_name
            return self.last_name < other.last_name
        else:
            if other.last_name:
                return self.first_name < other.last_name
            return self.first_name < other.first_name

现在您可以只使用sortedlist.sort而不带参数:

>>> contacts_list = [Contact("Luke"), Contact("Riyaan"), Contact("Amanda", "Benson")]
>>> sorted(contacts_list)
[Amanda Benson, Luke, Riyaan]

您需要一个自定义排序函数,当缺少姓氏时,该函数会将您的名字作为元组中的第一个值返回:

def name_sort(contact):
    if contact.lastName:
        return contact.lastName, contact.firstName
    return contact.firstName, ''

addressBook.contactsList.sort(key=name_sort)

您可以使用lambda和条件表达式将其适配到sort()调用中:

addressBook.contactsList.sort(key=lambda c: (c.lastName, c.firstName) if c.lastName else (c.firstName, ''))

我在这里为这两种情况都生成了一个2值元组,但是对于没有姓的情况,一个元素元组也应该足够了。你知道吗

如果这是您感兴趣的唯一排序顺序,那么您可能需要考虑提供rich comparison functions,这样您就可以在没有键的情况下对对象进行排序;然后比较对象本身并提供排序顺序。你知道吗

您不必实现所有丰富的比较方法,只需其中一个,加上__eq__(相等测试)和^{} class decorator

from functools import total_ordering

@total_ordering
class Contact(object):
    # ...

    def __eq__(self, other):
        if self.lastName != other.lastName:
            return False
        return self.firstName == other.firstName

    def __lt__(self, other):
        if not self.lastName:
            if not other.lastName:
                return self.firstName < other.firstName
            return self.firstName < other.lastName
        return (self.lastName, self.firstName) < (other.lastName, other.firstName)

相关问题 更多 >

    热门问题