У меня возникла проблема с использованием DateTime в качестве ключа dict. Моя цель - предоставить информацию из одного источника данных, который включает в себя Datetime, а затем искать в словаре и возвращать все значения для ключей, которые находятся в течение 2 дней + - ввода DateTime.
Например, моим вводом будет: datetime.datetime(2018, 9, 20, 12, 48)
Мой словарь для ссылки будет выглядеть следующим образом: example = {datetime.datetime(2018, 9, 20, 14, 43):'A', datetime.datetime(2018, 9, 18, 19, 41):'B', datetime.datetime(2018, 9, 15, 9, 12):'C'}
В этом случае я бы вернулся: A, B
Я рассмотрел сортировку словаря, а затем создание словаря индексов, возможно, для нечетных дат, а затем ввода даты ввода, определения базовой даты + - 2 даты ввода, ссылки на индекс dict, а затем использования этих индексов для цикл через ссылку dict только между индексами и вернуть все значения, которые есть.
Моя основная проблема заключается в том, что я не могу предсказать, что такое datetimes, или время ввода, поэтому я просто не уверен, могу ли я возвращать значения для диапазона ключей в dict, кроме как путем прокрутки индекса ключей в отсортированном порядке. Выполнение цикла for для всех ключей здесь неэффективно из-за количества ключей, которые нужно просмотреть - я уже сокращаю этот список, дедуплицируя как можно больше и только принося минимальный объем справочных данных.
Еще один пункт состоит в том, что мои входы будут составлять 100 000 секунд, чтобы искать, многие из которых будут составлять минуты, секунды или часы друг от друга, поэтому уменьшение количества поисков и циклов будет необходимо для сохранения времени выполнения,
Я прошу прощения, если это не совсем правильный вопрос с полным кодом, чтобы посмотреть, но я в принципе не уверен, с чего начать эту проблему, поэтому я не думал, что это поможет кому-либо добавить что-нибудь еще, кроме, например, ввода и словарь с целью вывода.
Сначала соберите словарные даты и преобразуйте словарь в список отсортированных кортежей:
dic_dates = {
datetime.datetime(2018, 9, 20, 14, 43):'A',
datetime.datetime(2018, 9, 18, 12, 41):'B',
datetime.datetime(2018, 9, 15, 9, 12):'C'
}
sorted_dates = sorted(dic_dates.items())
Затем используйте bisect, чтобы найти позицию вашей даты внутри этого списка:
dat = datetime.datetime(2018, 9, 20, 12, 48)
insert_index = bisect.bisect_left(sorted_dates, (dat,None))
Взгляните с этой позиции налево и сломайте, как только элемент не проверит условие, затем выполните то же самое, начиная с позиции вправо. (Вы можете использовать свои собственные условия, поскольку я обнаружил, что в вашем примере это было неясно - +-2days не следует выбирать "B" IMO, но это не так)
if insert_index:
#if insert_index = 0, do not loop on left side
dat_min = dat - datetime.timedelta(days=2)
for d in sorted_dates[insert_index-1::-1]:
if d[0] > dat_min:
print(d[1])
else:
break
dat_max = dat + datetime.timedelta(days=2)
for d in sorted_dates[insert_index:]:
if d[0] < dat_max:
print(d[1])
else:
break
Один пример реализации bisct_left:
def bisect_left(l, e, start = 0):
if not l:
return start
pos = int(len(l)/2)
if l[pos] < e and (pos+1 >= len(l) or l[pos+1] > e):
return start + pos + 1
elif l[pos] >= e:
return bisect_left(l[:pos], e, start)
else:
return bisect_left(l[pos:], e, start+pos)
Я настоятельно рекомендую вам использовать bisect, поскольку он будет более быстрым и надежным.