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

时间:2018-12-12 16:21:25

标签: python sorting attributes case-sensitive case-insensitive

我正在使用Python 3的attrgetter模块中的operator函数来对对象(命中)列表进行排序。每个对象都有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字段以大写字母开头的实例之后,对上述对象进行 排序。 ,“咖啡”甚至“动物园”。

我想使用类似casefold()之类的函数,以便大写字母在其小写字母的旁边和后面排序。但是,casefold()仅对字符串有效,因此使用key = attrgetter(attribute).casefold()返回AttributeError。

如何保留sort_hits_by_attribute()的功能(即,按在函数调用期间传递的属性进行排序),但在执行此操作时强制Python使用不同的顺序{aAbBcCdDeE ...}?

1 个答案:

答案 0 :(得分:0)

由于@KylePDavis,我找到了答案here,他提供了一种通用的解决方案,可以将属性作为参数传递。密钥是使用lambda函数定义密钥。

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

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)

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