Я пытаюсь отсортировать вложенный список по дате (что могу). Затем, если в списке есть повторяющиеся даты, отсортируйте повторяющиеся даты по времени.
Первая часть списка — это дата или время, вторая часть — индекс.
Один и тот же индекс в обоих списках означает, что они принадлежат друг другу:
[b'05-07-2024', 0]
принадлежит [b'15-21-00', 0]
[b'16-08-2024', 1]
принадлежит [b'23-41-01', 1]
Я могу сортировать один из списков за раз следующим образом:
index_list = []
for _, index in date_list:
index_list.append(index)
index_list
это:
[0, 1, 2]
Но index
1 и 2 на самом деле следует поменять местами в этом случае, потому что это списки:
date_list = [[b'05-07-2024', 0], [b'16-08-2024', 1], [b'16-08-2024', 2]]
time_list = [[b'15-20-55', 2], [b'15-21-00', 0], [b'23-41-01', 1]]
В конце концов мне нужен список индексов в правильном порядке.
В данном случае это будет:
[0, 2, 1]
Да, я знаю, но в моем случае мне нужно иметь два отдельных списка.
Да, но решением будет хотя бы временно создать эту лучшую структуру, даже если вы ее не сохраните.
Я уже использую его таким образом, но теперь хочу, чтобы он работал с двумя отдельными списками.
Почему? Это ужасно неудобный способ хранения данных.
Плохая конструкция модели данных приводит к неэффективному и сложному в обслуживании коду. Почему бы не поступить правильно и не пересмотреть источник данных?
Почему [b'15-20-55', 2]
находится в индексе 0, а не в индексе 2? Вы как-то перетасовали записи?
Или это потому, что вы контрпродуктивно разобрались time_list
?
Что делать, если индекс присутствует в одном из списков, но отсутствует в другом? Что делать, если индекс появляется в одном из списков несколько раз?
Что я делаю, так это сортирую список раньше, а затем добавляю соответствующий индекс в конец.
Списки всегда одинаковой длины
То есть вы действительно усложнили задачу по сравнению с исходными данными?
Если так сказать, то с чего бы было сложнее. Я думал, что это уже на шаг ближе
Скорее всего, это на шаг или два дальше. И смотрите xyproblem.info
Объедините дату и время в объект datetime
, после чего вы сможете просто сортировать по ним.
from datetime import datetime
sorted_indexes = sorted(
[idx for date, idx in date_list],
key=lambda idx: datetime.strptime(
f"{date_list[idx][0].decode('utf-8')} {next(t[0] for t in time_list if t[1] == idx).decode('utf-8')}",
'%d-%m-%Y %H-%M-%S'
)
)
Выход:
[0, 2, 1]
Главное — найти подходящую структуру данных, которая позволит вам напрямую использовать встроенную функцию sorted
.
Например, если ваши строки даты были в формате ГГГГ-ММ-ДД и ваши данные были структурированы следующим образом:
data = [
('2024-07-05', b'15-21-00', 0),
('2024-08-16', b'23-41-01', 1),
('2024-08-16', b'15-20-55', 2)
]
тогда ты мог бы использовать
sorted_indexes = [i for date, time, i in sorted(data)]
потому что sorted
сортирует списки кортежей лексикографически (т. е. сначала по дате, затем равные даты по времени и, в качестве бонуса, равные числа по индексу).
Поскольку у вас нет данного формата и структуры, вам необходимо ее создать (временно).
Вы можете использовать модуль datetime
для преобразования каждой строки даты:
from datetime import datetime
def convert_date(date):
"""Convert byte string in DD-MM-YYYY to Unicode string in YYYY-MM-DD format."""
return datetime.strptime(date.decode(), "%d-%m-%Y").strftime("%Y-%m-%d")
Вы можете использовать словарь, чтобы объединить соответствующие даты и время:
tmp = {}
for date, i in date_list:
tmp[i] = [convert_date(date)]
for time, i in time_list:
tmp[i].append(time) # assuming that i was already contained in date_list
data = [(date, time, i) for i, (date, time) in tmp.items()]
Вы можете поместить все в функцию, чтобы сохранить порядок:
def sort_dates_and_times(dates, times):
tmp = {}
for date, i in dates:
tmp[i] = [convert_date(date)]
for time, i in times:
tmp[i].append(time) # assuming that i was already contained in date_list
data = [(date, time, i) for i, (date, time) in tmp.items()]
return [i for date, time, i in sorted(data)]
sorted_indexes = sort_dates_and_times(date_list, time_list)
Другой подходящей структурой данных может быть
data = {
0: ('2024-07-05', b'15-21-00'),
1: ('2024-08-16', b'23-41-01'),
2: ('2024-08-16', b'15-20-55')
}
который, кстати, уже существует, как tmp
выше.
(The difference between tuples and lists as values doesn't matter now.)
Тогда вместо постобработки вывода sorted
для получения индексов,
data = [(date, time, i) for i, (date, time) in tmp.items()]
return [i for date, time, i in sorted(data)]
вы должны использовать аргумент key
, чтобы указать сортировку индексов не по индексам, а по соответствующим датам и времени:
def date_time_of_index(i):
return tmp[i]
return sorted(tmp, key=date_time_of_index)
Или более кратко:
return sorted(tmp, key=lambda i: tmp[i])
Или еще более лаконично (as suggested by no comment in a comment):
return sorted(tmp, key=tmp.get)
Хм, ок. Вместо этого я бы предложил структуру данных tmp
.
Создайте лучшую структуру данных, в которой дата и время принадлежат одному и тому же индексу. Тогда сортировка будет тривиальной.