在Python中对异构对象列表进行排序

5 投票
4 回答
3215 浏览
提问于 2025-04-15 14:59

我有一些自定义的对象和字典,我想把它们排序。我想把对象和字典一起排序。对象是根据某个属性来排序,而字典是根据一个键来排序。

object.name = 'Jack'
d = {'name':'Jill'}

sort_me =[object, d]

我该如何使用对象的名称属性和字典的“名称”键来排序这个列表呢?

4 个回答

1

这个方法对我有效。需要注意的是,sort() 这个函数不会返回一个排序好的列表,而 sorted() 会返回一个排序好的列表。所以如果你想把这个列表传给模板,你应该在参数中使用 sorted,或者在传递列表作为参数之前先用 sort 排序。

itemized_action_list = list(chain(detection_point.insertbodyaction_set.all(),
                                  detection_point.insertheaderaction_set.all(),
                                  detection_point.modifybodyaction_set.all(),
                                  detection_point.modifyheaderaction_set.all(),
                                  detection_point.removebodyaction_set.all(),
                                  detection_point.removeheaderaction_set.all(),
                                  detection_point.redirectaction_set.all()))

sorted(itemized_action_list, key=attrgetter('priority'))
3
sort_me.sort(key=attr_or_itemgetter('name'))

这里的 attr_or_itemgetter() 是一个函数:

class attr_or_itemgetter(object):
    def __init__(self, name):
        self.name = name
    def __call__(self, obj):
        try: return getattr(obj, name)
        except AttributeError:
            return obj[name]

注意:这个函数故意不检查输入是不是字典类型,所以当你对一个字典使用 attr_or_itemgetter('items') 时,它会返回 dict.items 这个方法。

8

你可能想要的是使用 sorted() 函数中的 key= 选项,这个选项可以让你提供一个函数,这个函数会为每个元素返回一个排序的关键字。这个函数可以检查它接收到的参数类型,并根据不同的类型采取不同的操作。例如:

import types

class obj(object):
    def __init__(self, arg):
        self.name = arg

def extract_name(obj):
    if type(obj) is types.DictType:
        return obj['name']
    else:
        return obj.__dict__['name']

d = { 'name': 'Jill'}    
print sorted([obj('Jack'), d], key=extract_name)

想了解更多信息,可以去 Python wiki 查看。

RichieHindle 提出的使用 isinstance 的建议很好。而且我想,支持任意元素名称而不是死板地写 'name' 也不错:

def extract_elem_v2(elem_name):
    def key_extractor(obj):
        dct = obj if isinstance(obj, dict) else obj.__dict__
        return dct[elem_name]
    return key_extractor

你可以这样使用:

print sorted(list_of_stuff, key=extract_elem_v2('name'))

撰写回答