Сортировка списка объектов по нескольким атрибутам, когда пользователь выбирает, каким атрибутам отдавать приоритет

Я пытаюсь отсортировать список, содержащий следующий объект по его атрибутам:

@dataclass
class Room():
    house_num: int
    room_num: int
    view: str

Я понял, как сортировать по нескольким атрибутам с помощью следующей строки:

all_rooms.sort(key=lambda r: (r.house_num, r.room_num, r.view))

Но я хочу, чтобы пользователь мог указать порядок приоритета атрибутов в файле конфигурации. Например, если в конфигурационном файле указано, что приоритет должен отдаваться сначала виду, а затем номеру дома и последнему номеру комнаты, приведенная выше строка будет выглядеть так:

all_rooms.sort(key=lambda r: (r.view, r.house_num, r.room_num))

Но я не уверен, как этого добиться. Я не хочу, чтобы пользователю приходилось вручную изменять порядок внутри sort(). Текущий файл конфигурации, который у меня есть, представляет собой файл YAML и, вероятно, будет выглядеть так:

priority: [view, house_num, room_num]

Какие-либо предложения?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
52
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать vars следующим образом

from functools import partial

class Room:
  def __init__(self, house_num, room_num, view):
    self.house_num = house_num
    self.room_num = room_num
    self.view = view
  def __str__(self):
    return "{0.room_num} {0.house_num} {0.view}".format(self)
    
room1 = Room(3, 1, "a")
room2 = Room(2, 1, "b")
rooms = [room1, room2]
def sort_(r, priority):
  vals = []
  for p in priority:
    vals.append(vars(r)[p])
  return tuple(vals)

priority = ['view', 'house_num', 'room_num']
sorter = partial(sort_, priority=priority)
for room in sorted(rooms, key=sorter):
  print(room)
Ответ принят как подходящий

Вместо использования lambda вы можете создать функцию и использовать getattr для получения значений атрибутов в предпочтительном порядке:

priority = ['view', 'house_num', 'room_num']

def evaluate(room):
    values = [getattr(room, p) for p in priority]
    return tuple(values)

all_rooms.sort(key=evaluate)

Здесь как нельзя лучше подходит operator.attrgetter:

from operator import attrgetter

priority = ['view', 'house_num', 'room_num']

all_rooms.sort(key=attrgetter(*priority))

Другие вопросы по теме