【问题标题】:Custom dictionary lookup in PythonPython中的自定义字典查找
【发布时间】:2011-04-27 18:46:30
【问题描述】:

如果我有这样的字典

>>> d = {10: 3, 100: 2, 1000: 1}

我可以输入如下内容:

>>> d.get(10), d.get(100), d.get(1000)
(3, 2, 1)

虽然我希望如果没有找到给定的键,则返回与给定键最近的键对应的值:

>>> d.get(20), d.get(60), d.get(200)
(3, 2, 2)

Python 中的结果是

(None, None, None)

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

谢谢

【问题讨论】:

标签: dictionary python


【解决方案1】:

您可以从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))

打印

(3, 2, 2)

注意get()的复杂度不再是O(1),而是O(n)。

【讨论】:

  • 这会导致查找 O(n),因此请谨慎使用。也许你应该给它一个不同的名字。
  • +1 很好地使用 min/key,一个微不足道的优化可能是测试直接命中。 if key not in self: key = min(....
【解决方案2】:

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]

【讨论】:

    【解决方案3】:

    查看此食谱Fuzzy matching dictionary

    【讨论】:

      猜你喜欢
      • 2013-03-01
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 2019-06-03
      • 2023-03-05
      相关资源
      最近更新 更多