Как отсортировать два вложенных списка, связанных индексами

Я пытаюсь отсортировать вложенный список по дате (что могу). Затем, если в списке есть повторяющиеся даты, отсортируйте повторяющиеся даты по времени.

Первая часть списка — это дата или время, вторая часть — индекс.

Один и тот же индекс в обоих списках означает, что они принадлежат друг другу:

  • [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]

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

mkrieger1 17.08.2024 21:15

Да, я знаю, но в моем случае мне нужно иметь два отдельных списка.

Kelvin Hollander 17.08.2024 21:19

Да, но решением будет хотя бы временно создать эту лучшую структуру, даже если вы ее не сохраните.

mkrieger1 17.08.2024 21:20

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

Kelvin Hollander 17.08.2024 21:22

Почему? Это ужасно неудобный способ хранения данных.

no comment 17.08.2024 21:29

Плохая конструкция модели данных приводит к неэффективному и сложному в обслуживании коду. Почему бы не поступить правильно и не пересмотреть источник данных?

trincot 17.08.2024 21:31

Почему [b'15-20-55', 2] находится в индексе 0, а не в индексе 2? Вы как-то перетасовали записи?

no comment 17.08.2024 21:34

Или это потому, что вы контрпродуктивно разобрались time_list?

no comment 17.08.2024 21:39

Что делать, если индекс присутствует в одном из списков, но отсутствует в другом? Что делать, если индекс появляется в одном из списков несколько раз?

no comment 17.08.2024 21:43

Что я делаю, так это сортирую список раньше, а затем добавляю соответствующий индекс в конец.

Kelvin Hollander 17.08.2024 22:21

Списки всегда одинаковой длины

Kelvin Hollander 17.08.2024 22:21

То есть вы действительно усложнили задачу по сравнению с исходными данными?

no comment 17.08.2024 22:34

Если так сказать, то с чего бы было сложнее. Я думал, что это уже на шаг ближе

Kelvin Hollander 17.08.2024 22:49

Скорее всего, это на шаг или два дальше. И смотрите xyproblem.info

no comment 17.08.2024 23:23
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
14
87
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Объедините дату и время в объект 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.

no comment 17.08.2024 22:00

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