attrgetter: изменение порядка по умолчанию при сортировке по атрибуту объекта - PullRequest
0 голосов
/ 12 декабря 2018

Я использую функцию attrgetter из модуля operator Python 3 для сортировки списка объектов (попаданий).Каждый объект имеет 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 голосов
/ 12 декабря 2018

Я нашел ответ здесь , благодаря @KylePDavis, который предоставил обобщенное решение, в котором атрибут может быть передан в качестве аргумента.Ключ определяет ключ с помощью функции 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)

Я не помечал этот вопрос как дубликат, потому что предпочтительный ответ на указанный вопрос не является ответом, который был важен специально для этого случая.

...