在Python字典中选择日期范围
我有一个字典:
history = {
"2008-11-17": 41,
"2010-05-28": 82,
"2008-11-14": 47,
"2008-11-13": 60,
"2008-11-12": 56,
"2008-11-11": 55,
"2008-11-10": 98,
"2008-11-19": 94,
"2008-11-18": 94,
"2004-05-27": 82,
"2004-05-26": 45,
"2004-05-25": 70,
# there's more ...
}
我该如何定义一个生成器函数 get_records(dict_history, str_from_date, str_to_date)
来输出 日期: 记录
的条目呢?
我知道怎么把 datetime
对象转换成我想要的任何字符串格式。不过,我在这个问题上遇到的主要困难是:
dict
(字典)是无序的。dict
的键是字符串。- 日期不是连续的。
到目前为止,这是我能想到的:
from datetime import datetime, timedelta
def get_records(history, start_date, end_date):
fmt = "%Y-%m-%d"
dt = timedelta(days=1)
present_date = datetime.strptime(start_date, fmt)
end_date = datetime.strptime(end_date, fmt)
while present_date <= end_date:
present_string = present_date.strftime(fmt)
try:
yield (present_string, history[present_string])
except KeyError:
pass
present_date += dt
有没有更有效的方法来做到这一点呢?
更新(2011年8月2日)
我在 ActiveState 找到了一个 SortedCollection
类,也是由 Raymond Hettinger 提供的。
5 个回答
0
当然可以!请看下面的内容:
这段代码是用来处理某些数据的。它首先会检查数据的格式是否正确,如果不正确,就会给出一个错误提示。接着,如果数据格式没问题,代码会继续执行,进行一些计算或者数据处理的操作。
在编程中,检查数据格式是非常重要的,因为如果数据不符合要求,后面的操作可能会出错,导致程序崩溃或者结果不正确。
总之,这段代码的主要目的是确保输入的数据是有效的,然后再进行后续的处理。
def get_records(history, str_from_date, str_to_date)
return sorted((k,v) for k,v in history.iteritems() if str_from_date<=k<=str_to_date)
0
history = { "2008-11-17": 41,
"2010-05-28": 82,
"2008-11-14": 47,
"2008-11-13": 60,
"2008-11-12": 56,
"2008-11-11": 55,
"2008-11-10": 98,
"2008-11-19": 94,
"2008-11-18": 94,
"2004-05-27": 82,
"2004-05-26": 45,
"2004-05-25": 70 }
def get_records(dict_history, str_from_date, str_to_date):
for k,v in sorted(dict_history.items()):
if k>str_to_date:
break
if k>=str_from_date:
yield (k,v)
print history.items()
print
print list( get_records(history, '2005-05-21', '2008-12-25'))
这些日期是以字符串形式表示的,格式是 'yyyy-mm-jj'。
如果按照字典顺序对这些字符串进行排序,得到的结果和根据它们代表的日期进行排序是一样的。
使用 sorted(dict_history.items()) 会得到一个元组的列表。Python 会根据元组的第一个元素对这个列表进行排序。
因为字典中的每个键都是唯一的,所以在排序时不会出现混淆。
编辑 1
针对你提到的性能问题:
history = { "2008-11-17": 41,
"2010-05-28": 82,
"2008-11-14": 47,
"2008-11-13": 60,
"2008-11-12": 56,
"2008-11-11": 55,
"2008-11-11": 02,
"2008-11-10": 98,
"2008-11-19": 94,
"2008-11-18": 94,
"2004-05-27": 82,
"2004-05-26": 45,
"2004-05-25": 70 }
import bisect
def get_records(dict_history, str_from_date, str_to_date):
sorted_keys = sorted(dict_history.iterkeys())
start = bisect.bisect_left(sorted_keys,str_from_date)
end = bisect.bisect_right(sorted_keys,str_to_date)
for date in sorted(dict_history.iteritems())[start:end]:
yield date
print history.items()
print
print list( get_records(history, '2005-05-21', '2008-12-25'))
7
我会遍历这个字典,然后返回那些符合条件的项目:
def get_records(history, start_date, end_date):
for date, entry in history.iteritems():
if start_date <= date <= end_date:
yield date, entry
注意,你的日期格式可以直接用字符串比较,比如用 <
和 >
,而不需要先转换成 datetime
类型。
另外要注意,这个函数返回的匹配项是没有特定顺序的。