map :: lower_bound()等效于python的dict类?

时间:2012-02-18 18:06:32

标签: python stl

我正在编写一些代码,要求我获取键的下限(为简单起见,忽略位于集合中最小键下方的键)。

在C ++中,使用std :: map(作为最具可比性的数据类型)我只需使用lower_bound()来返回迭代器。

我的Pythonfoo不是那么好,但我猜测(如果Python还没有办法做到这一点),这将是一个很好的使用lambda函数......

检索给定索引的下界键的Pythonic方法是什么?

如果问题太抽象,这就是我实际上要做的事情:

我有一个按日期索引的Python dict。我希望能够使用日期来查找dict,并返回与指定键的下限相关联的值。

片段如下:

mymap = { datetime.date(2007, 1, 5): 'foo',
          datetime.date(2007, 1, 10): 'foofoo',
          datetime.date(2007, 2, 2): 'foobar',
          datetime.date(2007, 2, 7): 'foobarbar' }

mydate = datetime.date(2007, 1, 7)

# fetch lbound key for mydate from mymap
def mymap_lbound_key(orig):
    pass # return the lbound for the key 

我真的不想循环键,寻找第一个键< =提供的键,除非没有更好的选择......

4 个答案:

答案 0 :(得分:7)

Python的dict类没有此功能;你需要自己写。如果键已经排序了肯定会很方便,不是吗,所以你可以对它们进行二进制搜索并避免迭代它们全部?在这种情况下,我将查看sorteddict包中的blist类。 http://pypi.python.org/pypi/blist/

答案 1 :(得分:4)

如果你的日期有某种程度的重载,它可以比较bisect module的内容。

最小整数编码示例:

from bisect import bisect_left

data = {
    200 : -100,
    -50 : 0,
    51 : 100,
    250 : 200
}

keys = list(data.keys())

print data[  keys[ bisect_left(keys, -79) ]  ]

答案 2 :(得分:3)

当我想要类似于c ++地图的东西时,我使用的是SortedDict。您可以使用irange来获取给定键是下限的键的迭代器 - 我认为这是std::lower_bound的工作原理。

代码:

from sortedcontainers import SortedDict
sd = SortedDict()
sd[105] = 'a'
sd[102] = 'b'
sd[101] = 'c'

#SortedDict is sorted on insert, like std::map
print(sd)

# sd.irange(minimum=<key>) returns an iterator beginning with the first key not less than <key>
print("min = 100", list(sd.irange(minimum=100)))
print("min = 102", list(sd.irange(minimum=102)))
print("min = 103", list(sd.irange(minimum=103)))
print("min = 106", list(sd.irange(minimum=106)))

输出:

SortedDict(None, 1000, {101: 'c', 102: 'b', 105: 'a'})
min = 100 [101, 102, 105]
min = 102 [102, 105]
min = 103 [105]
min = 106 []

答案 3 :(得分:0)

仍然不确定“下限”是什么:查询日期之前/之后的最新日期?

无论如何,因为dict没有对其键强加固有顺序,所以你需要一个不同的结构。将您的密钥存储在一些结构中,以保持其排序并允许快速搜索。

最简单的解决方案是将日期排序存储在(日期,值)列表中,然后进行二分搜索以放大所需的区域。如果你需要/想要更好的性能,我认为你需要一个b树。