attrgetter:按对象属性排序时更改默认顺序



我正在使用Python 3的operator模块中的attrgetter函数来对对象列表(命中(进行排序。每个对象有12个属性,可以向我的排序函数提供其中的任何属性,以便以所需的任何方式对列表进行排序。我感兴趣的排序属性包含字符串。这是我的代码中的相关片段。

from operator import attrgetter
...
def sort_hits_by_attribute(hits, attribute, backwards = False):
"""Takes a lits of hits and sorts them by some attribute.
"""
return sorted(hits, key = attrgetter(attribute), reverse = backwards)

下面是一个"命中"对象及其属性的示例。

name: ...
entity_1: coffee cultivation
entity_2: ...
full_statement: ...
category: ...
rule: ...
syn_configs: ...
lex_conditions: ...
sentence_number: ...
close_call: False
message: ...
id: 119

如果我按属性entity_1对对象列表进行排序,那么上面的对象将被排序在一个实例之后,该实例的entity_1字段以大写字母开头:例如,"Coffee"甚至"Zoo"。

我想使用一个类似casefold()的函数,这样大写字母就可以在小写字母的前后排序。但是,casefold()仅对字符串有效,因此使用key = attrgetter(attribute).casefold()会返回AttributeError。

如何保留sort_hits_by_attribute()的功能(即,根据函数调用过程中传递的属性进行排序(,但在执行此操作时强制Python使用不同的排序{aAbBcCdDeE…}?

我在这里找到了答案,这要归功于@KylePDavis,他提供了一个通用的解决方案,可以将属性作为参数传入。密钥使用lambda函数定义密钥。

我的代码现在如下所示。注意输入检查,以验证(1(列表不是空的,以及(2(感兴趣的属性是否确实是可以使用casefold()排序的类型(str(。

def sort_hits_by_attribute(hits, attribute, backwards=False):
"""Takes a lits of hits and sorts them by some attribute.
For instance, group duplicate relation hits together by sorting
on full_statement.
"""
if hits:
if isinstance(attrgetter(attribute)(hits[0]), str):
return sorted(hits, 
key = lambda A: attrgetter(attribute)(A).casefold(), 
reverse = backwards)
else:
return sorted(hits, 
key = attrgetter(attribute), 
reverse = backwards)

我没有将这个问题标记为重复,因为引用的问题的最喜欢的答案并不是专门针对本案的重要答案。

最新更新