在Python字典中选择日期范围

4 投票
5 回答
8229 浏览
提问于 2025-04-16 22:39

我有一个字典:

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 对象转换成我想要的任何字符串格式。不过,我在这个问题上遇到的主要困难是:

  1. dict(字典)是无序的。
  2. dict 的键是字符串。
  3. 日期不是连续的。

到目前为止,这是我能想到的:

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 类型。

另外要注意,这个函数返回的匹配项是没有特定顺序的。

撰写回答