python:检索字典或集合中的天花板键和楼层键

时间:2013-07-25 16:49:00

标签: python dictionary map tree

我有一串带整数键的字典。对于我没有的按键,我希望能够在它想要检索的键之前和之后检索最小和最大的键,但这不存在。
java中的Treemap类有两个完全相同的方法:ceilingkey()floorkey()

  

如何使用python执行此操作?

作为一个例子,我有一个这样的字典:

 { 1: "1", 4: "4", 6: "6" ..., 100: "100" } 

如果我要求输入密钥1,我会检索"1", 但是,如果我查找密钥3,我应该KeyError,因此可以获得floor(3) = 1ceil(3) = 4

3 个答案:

答案 0 :(得分:5)

def floor_key(d, key):
    if key in d:
        return key
    return max(k for k in d if k < key)

def ceil_key(d, key):
    if key in d:
        return key
    return min(k for k in d if k > key)

我不确定你想如何处理边境条件。请注意,如果要求键的下限/上限低于/高于dict中的任何内容,则会引发异常(ValueError)。

答案 1 :(得分:2)

您可以在此处使用bisect模块,以防未找到密钥,然后它可以在O(log N)时间内找到ceil和floor值。:

>>> import bisect
>>> from random import randint
def get_value(dic, key):
    if key in dic:
        return dic[key]
    else:
        ind = bisect.bisect(keys, key)
        d = {}
        if ind > 0:
            d["floor"] = dic[keys[ind-1]]
        if ind < len(keys):
            d["ceil"] = dic[keys[ind]]
        return d
...     
>>> dic = {randint(0,100) : x  for x in xrange(10)}
>>> dic
{65: 6, 4: 5, 1: 7, 40: 8, 10: 4, 50: 0, 68: 2, 27: 9, 61: 3}

bisect创建排序的键列表:

>>> keys = sorted(dic)
>>> keys
[1, 4, 10, 27, 40, 50, 61, 65, 68]

现在使用功能:

>>> get_value(dic, 4)
5

3而言,ceil和floor都是可用的:

>>> get_value(dic, 3)
{'ceil': 5, 'floor': 7}

0小于最小键,因此仅返回ceil

>>> get_value(dic, 0)
{'ceil': 7}

对于大于最大键的键,将仅返回floor值:

>>> get_value(dic, 70)
{'floor': 2}

答案 2 :(得分:2)

这是一个有趣的使用bisect。

import bisect

def ceiling_key(d, key):
    keys = sorted(d.keys())
    idx = bisect.bisect_left(keys, key)
    if key in d:
        idx += 1
    return keys[idx]

def floor_key(d, key):
    keys = sorted(d.keys())
    idx = bisect.bisect_left(keys, key) - 1
    return keys[idx]


...

>>> ceiling_key(d, 1)
4
>>> ceiling_key(d, 2)
4
>>> ceiling_key(d, 4)
6
>>> ceiling_key(d, 3)
4
>>> ceiling_key(d, 2)
4
>>> ceiling_key(d, 1)
4
>>> ceiling_key(d, 0)
1
>>> ceiling_key(d, 6)
100
>>> floor_key(d, 6)
4
>>> floor_key(d, 7)
6
>>> floor_key(d, 101)
100
>>> floor_key(d, 100)
6