通过表达式查找python dict值

时间:2013-02-15 00:45:54

标签: python optimization

我有一个dix,其中包含键的unix纪元时间戳,如下所示:

lookup_dict = {
    1357899: {} #some dict of data
    1357910: {} #some other dict of data
}

除此之外,您知道,有数百万和数百万条目。我想一遍又一遍地将这个词汇分配。理想情况下,我希望能够在R中写出类似的内容,例如:

lookup_value = 1357900
dict_subset = lookup_dict[key >= lookup_value]
# dict_subset now contains {1357910: {}}

但是我承认,我找不到任何实际的证据,证明这是Python可以做的事情,而不是以某种方式迭代每一行。如果我正确理解Python(我可能不会),key in dict形式的键查找使用二进制搜索,因此非常快;在dict键上进行二进制搜索的任何方法?

2 个答案:

答案 0 :(得分:2)

要在不进行迭代的情况下执行此操作,您将需要按排序顺序排列的键。然后,您只需要对第一个>= lookup_value进行二进制搜索,而不是检查每个>= lookup_value

如果您愿意使用第三方库,那里有很多。想到的前两个是bintrees(使用红黑树,如C ++,Java等)和blist(使用B +树)。例如,使用bintrees,就像这样简单:

dict_subset = lookup_dict[lookup_value:]

这将是您希望的效率 - 基本上,它会在使用该子集的任何成本之上添加单个O(log N)搜索。 (当然,通常你想要对那个子集做什么就是迭代整个事情,最终结果是O(N)......但是你可能正在做一些不同的事情,或者这个子集只有100个中的10个密钥。)

当然有一个权衡。对基于树的映射的随机访问是O(log N)而不是“通常为O(1)”。此外,您的密钥显然需要完全排序,而不是可以使用(并且更难以自动检测并提出好的错误消息)。

如果您想自己构建,可以。你甚至不一定需要一棵树;只是一个有序的list个键和dict一起。您可以像JonClements建议的那样,在stdlib中使用list模块维护bisect。您可能希望将bisect打包以生成排序列表对象 - 或者更好的是,获取ActiveState或PyPI上的一个配方来为您执行此操作。然后,您可以将排序列表和dict一起包装到单个对象中,这样您就不会在不更新另一个对象的情况下意外更新一个。然后,如果需要,您可以将界面扩展为bintrees

答案 1 :(得分:0)

使用以下代码可以解决问题

some_time_to_filter_for = # blah unix time
# Create a new sub-dictionary
sub_dict = {key: val for key, val in lookup_dict.items() 
            if key >= some_time_to_filter_for}

基本上我们只是迭代你字典中的所有键并给出时间来过滤掉我们获取大于或等于该值的所有键并将它们放入我们的新字典中