首页 > 解决方案 > 如何按字符串属性对对象列表进行排序并使用“键”参数?

问题描述

我想list按一个属性对一些对象进行排序,但我也希望能够key在进行排序时指定一个(这些属性的)。我见过这样的答案它使用属性对对象进行排序,但我想允许除了(对于字符串)只是按字母顺序排序之外的其他排序逻辑。这是一个示例类和排序函数来说明我的意思:

class Pet:
    def __init__(self, name):
        self.name = name

    def __repr__(self): # for readability
        return 'Pet({})'.format(self.name)

def sort_pets(pets, reverse=False):
    pets.sort(reverse=reverse, key=lambda x : x.name)

Pet因此,使用此功能,我可以按对象列表对它们进行排序name

>>> pets = [Pet(i) for i in ['Dexter Lewis Cumberbatch', 'Alice', 'Bozo Bob', 'Cy']]
>>> sort_pets(pets)
>>> print(pets)
[Pet(Alice), Pet(Bozo Bob), Pet(Cy), Pet(Dexter Lewis Cumberbatch)]

我可以按字母顺序或按字母顺序反转(使用reverse)。但我想选择用不同的逻辑(比如名字长度、空格数、最后一个字母等)对宠物(按名字)进行排序。我可以为 制作一个key参数sort_pets,但我不能将它传递给 的key参数sort,因为它已经被用于访问name属性。有没有办法做到这一点?

标签: pythonsorting

解决方案


您可以通过在查找每个对象的属性时将key参数 fromsort_pets合并到函数中来做到这一点:lambda

def sort_pets(pets, reverse=False, key=None):
    if key is None:
        sortkey = lambda x : x.name
    else:
        sortkey = lambda x : key(x.name)
    pets.sort(reverse=reverse, key=sortkey)

因此,当 akey未传递给sort_pets时,对象仅按其name属性排序。如果通过了,则将该键应用于每个键name以构建新的lambda键功能。

现在您可以使用keyof对对象sort_pets进行排序,Pet就好像您只是在查看名称一样:

pets = [Pet(i) for i in ['Dexter Lewis Cumberbatch', 'Alice', 'Bozo Bob', 'Cy']]
print(sort_pets(pets))  #no additional sorting
print(sort_pets(pets, key=lambda x : len(x))) #sort by number of characters
print(sort_pets(pets, key=lambda x : len(x.split(' ')[0]))) #sort by length of first name
print(sort_pets(pets, key = lambda x : x[-1])) #sort by last character

输出:

[Pet(Alice), Pet(Bozo Bob), Pet(Cy), Pet(Dexter Lewis Cumberbatch)]
[Pet(Cy), Pet(Alice), Pet(Bozo Bob), Pet(Dexter Lewis Cumberbatch)]
[Pet(Cy), Pet(Bozo Bob), Pet(Alice), Pet(Dexter Lewis Cumberbatch)]
[Pet(Bozo Bob), Pet(Alice), Pet(Dexter Lewis Cumberbatch), Pet(Cy)]

推荐阅读