Python中的自定义字典查找

Pao*_*olo 12 python dictionary

如果我有这样的字典

>>> d = {10: 3, 100: 2, 1000: 1}
Run Code Online (Sandbox Code Playgroud)

我可以输入类似的东西:

>>> d.get(10), d.get(100), d.get(1000)
(3, 2, 1)
Run Code Online (Sandbox Code Playgroud)

虽然我想要,如果找不到给定的密钥,则返回与最近的密钥对应的给定密钥的值:

>>> d.get(20), d.get(60), d.get(200)
(3, 2, 2)
Run Code Online (Sandbox Code Playgroud)

相反,Python中的结果是

(None, None, None)
Run Code Online (Sandbox Code Playgroud)

什么是Pythonic实现我描述的行为的方法?

谢谢

Sve*_*ach 17

您可以派生自dict更改get()方法的行为:

class ClosestDict(dict):
    def get(self, key):
        key = min(self.iterkeys(), key=lambda x: abs(x - key))
        return dict.get(self, key)

d = ClosestDict({10: 3, 100: 2, 1000: 1})
print (d.get(20), d.get(60), d.get(200))
Run Code Online (Sandbox Code Playgroud)

版画

(3, 2, 2)
Run Code Online (Sandbox Code Playgroud)

注意,复杂性get()不再是O(1),而是O(n).

  • 这样可以查找O(n),因此请谨慎使用.也许你应该给它一个不同的名字. (3认同)
  • 也许是'get_closest`. (2认同)
  • +1很好地使用min/key,一个简单的优化可能是测试直接命中.`如果键不在自己:key = min(...`. (2认同)

Imr*_*ran 6

bisect模块允许快速查找排序列表中的插入位置.

from bisect import bisect_right

def closest_matches(data, query):
    keys = sorted(data)
    return [data[i] for i in (min(map(abs, (keys[p-1], keys[p]))) for p in (bisect_right(keys, k) for k in query))]

>>> d = {10: 3, 100: 2, 1000: 1}
>>> closest_matches(d, [20, 60, 200])
[3, 3, 2]
Run Code Online (Sandbox Code Playgroud)