Сортировать список Dict по нескольким ключам, включая список - PullRequest
1 голос
/ 05 апреля 2019

Я бы хотел отсортировать этот список диктов по ключу списка, а затем по дате. Я пытаюсь отсортировать слова по метке в соответствии с label_order, а затем по убыванию даты.

label_order = [3, 4, 2, 1]

data = [
    {'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
    {'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
    {'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
    {'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
    {'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
]

После сортировки будет выглядеть так:

data = [
    {'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
    {'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
    {'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
    {'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
    {'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
]

Я пробовал лямбда-выражения и itemgetter, но мне сложно комбинировать правильные стратегии для ключа сортировки. Может быть, он просто пытается сделать слишком много за один раз.

Буду признателен за любую помощь или направление.

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

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

from datetime import datetime

label_order = [3, 4, 2, 1]

data = [
    {'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
    {'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
    {'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
    {'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
    {'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
]

def descending_sort_key(item):
    return -label_order.index(item['label']), item['date']

data.sort(key=descending_sort_key, reverse=True)

Вуаля - без даты, математики или других хитростей.

1 голос
/ 05 апреля 2019

Более эффективный подход заключается в создании dict, который отображает элементы в label_order на индексы, так что вы можете использовать индексы в качестве ключей при выполнении сортировки:

keys = {n: i for i, n in enumerate(label_order)}
sorted(data, key=lambda d: (-keys[d['label']], d['date']), reverse=True)

Возвращает:

[{'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
 {'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
 {'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
 {'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
 {'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...