Сортировка объектов datetime в python
Задача заключается в подсчете времени, в которое горит лампочка, пока за ней смотрит наблюдатель. Из входных данных - отрезки включения и выключения лампочки, а также время наблюдения. Код выглядит так (знаю, громоздко):
from datetime import datetime
from typing import List, Optional
def sum_light(els: List[datetime],
start_watching: Optional[datetime] = None,
end_watching: Optional[datetime] = None) -> int:
if start_watching is None:
start_watching = els[0]
if end_watching is None:
end_watching = datetime.max
els = sorted(els + [start_watching] + [end_watching])
start = els.index(start_watching)
end = els.index(end_watching)
if start_watching is not None and end_watching is None:
return int(sum((on - off).total_seconds() for off, on in
zip(els[start + (start % 2 == 0)::2], els[start + (start % 2 == 0) + 1::2])))
elif start_watching is None and end_watching is not None:
return int(sum((on - off).total_seconds() for off, on in
zip(els[:end + 1:2], els[1:end + 1:2])))
elif start_watching is not None and end_watching is not None:
return int(sum((on - off).total_seconds() for off, on in
zip(els[start + (start % 2 == 0):end + 1:2], els[start + (start % 2 == 0) + 1:end + 1:2])))
else:
return int(sum((on - off).total_seconds() for off, on in
zip(els[::2], els[1::2])))
if __name__ == "__main__":
print("Example:")
print(
sum_light(
[
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 0, 10),
],
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 0, 10),
)
)
Следующий этап задачи - несколько лампочек (к входным данным добавляется номер лампочки, и теперь это объекты типа Tuple[datetime, int]. В коде могут быть как объекты tuple, так и просто объекты datetime, которые должны пониматься как первая лампочка (без индекса)).Код такой:
def sum_light(
els: List[Union[datetime, Tuple[datetime, int]]],
start_watching: Optional[datetime] = None,
end_watching: Optional[datetime] = None) -> int:
if start_watching is None:
start_watching = els[0]
if end_watching is None:
end_watching = datetime.max
els = [(elem, 1) if type(elem) is datetime else elem for elem in els] # Здесь привожу все элементы к общему виду
els = sorted(els + [start_watching] + [end_watching], key=lambda x: (x[0], x[1]))
Но теперь, когда я пытаюсь отсортировать список по объекту datetime и индексу, интерпретатор ругается:
els = sorted(els, key=lambda x: x[0])
TypeError: 'datetime.datetime' object is not subscriptable
Почему в первом случае код спокойно отсортировал список по datetime, а во втором выскакивает ошибка?
Ответы (1 шт):
Досконально изучив возможности сортировки, понял, что кортежи можно отсортировать с помощью модуля operator. Задав оператору itemgetter() второй объект кортежа, а именно число (в моем случае номер лампочки), я смог отсортировать список так, чтобы включение и выключение каждой лампочки шло друг за другом, что дает мне возможность узнать время работы лампочки, поочередно вычитая время выключения из времени включения с помощью zip.