как разработать расширяемый метод сортировки строк запроса в Python?

#python #python-3.x #sorting

#python #python-3.x #сортировка

Вопрос:

Мне нужно отсортировать строку запроса по различным параметрам. Например:
[url]/handler?sort=-key1,key2 Теперь сортировка выполняется в списке dicts в метаданных каждого dict следующим образом:

sorted(results_list, key=lambda obj:[(-obj["metadata"][x[0]] if x[1] == "desc" else obj["metadata"][x[0]]) for x in sort])

Параметры извлекаются из моего обработчика и передаются менеджеру логики для обработки сортировки. Этот код написан на python 3. Я хочу сделать этот механизм сортировки более расширяемым. В настоящее время это не позволит выполнять какую-либо сортировку, которая:

  1. Вне области действия свойства метаданных.
  2. не число (например, сортировка по алфавиту).

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

Итак, как мне следует переработать этот код, чтобы он был более расширяемым?

Ответ №1:

Что-то вроде этого:

вы должны иметь возможность передавать список SortInstruction через свой API ( handler ). get_sorted_list позаботится о фактической сортировке.

 from typing import NamedTuple

lst = [{'meta':{'k':12},'k1': 66,'k2': 'jack'},
       {'meta':{'k':99},'k1': 656,'k2': 'zoo'},
       {'meta':{'k':134},'k1': 166,'k2': 'dan'}]  

class SortInstruction(NamedTuple):
    in_meta_data: bool
    reverse: bool
    field_name: str
    
def get_sorted_list(sort_instructions):
    result = lst
    for si in sort_instructions:
        result = sorted(result, key = lambda x : x[si.field_name] if not si.in_meta_data else x['meta'][si.field_name] , reverse = si.reverse)
    return result
    
sorted_list = get_sorted_list([SortInstruction(True,False,'k'),SortInstruction(False,False,'k1')])

for entry in sorted_list:
    print(entry)
  

Ответ №2:

Чтобы сделать код более читаемым и простым в обслуживании, вы хотели бы расширить логику сортировки и дизайн НАДЕЖНЫМ образом.

Я бы посоветовал:

  1. Handler преобразует параметры из URL в context объект, который содержит их все.
  2. Handler передает context объект LogicManager , который определяет, какой список сортировать и каким способом.
  3. LogicManager отправьте список для сортировки и способ сортировки, как первоначально описано в URL, на Sorter , который сортирует списки, как описано.

    Таким образом, у каждого класса есть свое единственное предложение, и код проще поддерживать.
    Тем не менее, вы можете масштабировать сортировку, добавив больше Sorter потоков или микросервисов.