Как я могу получить ключи из словаря ftp_json с самой большой датой по маске из списка daily_updated?
daily_updated = ('kgrd', 'cvhd', 'metd')
ftp_json = {'kgrd0118.arj': 'Jan-18-2007',
'kgrd0623.arj': 'Jun-23-2005',
'kgrd0624.arj': 'Jun-24-2005',
'cvhd0629.ARJ': 'Jan-29-2021',
'cvhd1026.arj': 'Oct-26-2015',
'cvhd1125.ARJ': 'Nov-25-2019',
'cvhd0222.ARJ': 'Feb-22-2022',
'metd0228.ARJ': 'Feb-28-2022',
'metd0321.ARJ': 'Mar-26-2021',
}
result = ['kgrd0118.arj', 'cvhd0222.arj', 'metd0228.ARJ']
Я имею в виду, что "маска" = значение в списке daily_updated. Например, значение «kgrd» в ftp_json включает дату в конце имени («krgd0102», «krgd0103» и т. д.). Моя маска в примере — «krgd».
«маска» - это только первые 4 символа ключа?
Да, маска - это только первые 4 символа ключа.
используя numpy.argmax
и pandas.to_datetime:
import numpy as np
result = []
for d in daily_updated:
a = [(key,date) for key, date in ftp_json.items() if d in key]
index = np.argmax([pd.to_datetime(date) for key,date in a])
result.append(a[index][0])
Было бы хорошо указать, что это решение использует стороннюю библиотеку, которую необходимо установить и импортировать.
Я думаю, это библиотека numpy
Без сомнения, это можно сделать проще, но я думаю, что этот пример является наглядным способом сделать это со стандартной библиотекой.
from datetime import datetime
ftp_json = {
"kgrd0118.arj": "Jan-18-2007",
"kgrd0623.arj": "Jun-23-2005",
"kgrd0624.arj": "Jun-24-2005",
"cvhd0629.ARJ": "Jan-29-2021",
"cvhd1026.arj": "Oct-26-2015",
"cvhd1125.ARJ": "Nov-25-2019",
"cvhd0222.ARJ": "Feb-22-2022",
"metd0228.ARJ": "Feb-28-2022",
"metd0321.ARJ": "Mar-26-2021",
}
max_dates = {} # New dict for storing running maximums.
for k, v in ftp_json.items():
d = datetime.strptime(v, "%b-%d-%Y") # Use datetime for comparison.
# Here we return the previous tuple values if set for comparison.
# If they weren't set, do so now.
maxk, maxv, maxd = max_dates.setdefault(k[:4], (k, v, d))
if d > maxd: # Update the values is the current date is more recent.
max_dates[k[:4]] = (k, v, d)
# Validate we stored the correct values.
assert [v[0] for v in max_dates.values()] == [
"kgrd0118.arj",
"cvhd0222.ARJ",
"metd0228.ARJ",
]
Спасибо, очень просто и понятно для меня.
Вы можете воспользоваться параметром key
встроенной функции max
(и min
), чтобы наложить критерий упорядочения. Перед этим вам нужно превратить строку, содержащую даты, в объекты datetime
, которые поставляются вместе со своим собственным порядком, __lt__
и т. д., реализацией. Здесь документ для форматирования даты.
Обратите внимание, что необходим минимальный объект date
, он будет использоваться как «фальшивое» значение, чтобы избежать помех от всех других масок в поиске максимального термина. Я, естественно, зафиксировал его как минимум среди всех дат.
import datetime
daily_updated = ('kgrd', 'cvhd', 'metd')
ftp_json = {'kgrd0118.arj': 'Jan-18-2007',
'kgrd0623.arj': 'Jun-23-2005',
'kgrd0624.arj': 'Jun-24-2005',
'cvhd0629.ARJ': 'Jan-29-2021',
'cvhd1026.arj': 'Oct-26-2015',
'cvhd1125.ARJ': 'Nov-25-2019',
'cvhd0222.ARJ': 'Feb-22-2022',
'metd0228.ARJ': 'Feb-28-2022',
'metd0321.ARJ': 'Mar-26-2021',
}
def date_formatter(mydate):
return datetime.datetime.strptime(mydate, '%b-%d-%Y').date()
# smallest date
day_zero = datetime.datetime.strptime(min(ftp_json.values(), key=lambda d: date_formatter(d)), '%b-%d-%Y').date()
# get the maximum for each mask
m = [max(ftp_json.items(), key=lambda pair: date_formatter(pair[1]) if pair[0].startswith(pattern) else day_zero) for pattern in daily_updated]
print([i for i, _ in m])
Выход
['kgrd0118.arj', 'cvhd0222.ARJ', 'metd0228.ARJ']
РЕДАКТИРОВАТЬ
Чтобы сделать его более читабельным (а не однострочным), можно ввести декоратор, который будет передаваться в параметр key
max
(min
).
# ...
def date_formatter(mydate):
return datetime.datetime.strptime(mydate, '%b-%d-%Y').date()
# smallest date
day_zero = datetime.datetime.strptime(min(ftp_json.values(), key=lambda d: date_formatter(d)), '%b-%d-%Y').date()
# decorator containing the logic of the comparison criteria
def ordering(pattern):
def _wrapper(pair):
if pair[0].startswith(pattern):
# cast to date-object if the "mask"/pattern is correct
return date_formatter(pair[1])
else:
# return default smallest date-object -> will not influence the max-function
return day_zero
return _wrapper
# get the maximum for each mask
m = [max(ftp_json.items(), key=ordering(pattern)) for pattern in daily_updated]
Что вы имеете в виду под маской? Маска обычно относится к последовательности битов, используемых для побитовых операций, но ваши данные — это все строки, а не целые числа.