【问题标题】:Python: Efficient lookup by intervalPython:按间隔高效查找
【发布时间】:2019-07-31 05:46:02
【问题描述】:

我有一个大查找表,其中键是一个区间:

| min | max | value   |
|-----|-----|---------|
| 0   | 3   | "Hello" |
| 4   | 5   | "World" |
| 6   | 6   | "!"     |
| ... | ... | ...     |

目标是创建一个查找结构my_lookup,它为每个整数返回一个值,具体取决于整数所在的范围。 例如:2 -> "Hello"3 -> "Hello"4 -> "World"

这是一个实现我想要的实现:

d = {
  (0, 3): "Hello",
  (4, 5): "World",
  (6, 6): "!"
}

def my_lookup(i: int) -> str:
  for key, value in d.items():
    if key[0] <= i <= key[1]:
      return value

但循环遍历所有条目似乎效率低下(实际查找表包含 400.000 行)。有更快的方法吗?

【问题讨论】:

  • 通常,您将间隔存储在 interval tree 中。
  • 间隔是否保证不相交?
  • 是的,间隔是不相交的。并且在查找表初始化后会有数百万次查找......所以如果排序提高查找效率,那绝对是值得的。
  • 给你一些背景知识:实际的问题是从网络服务器上的 IP 地址确定用户的国家。
  • 等等,实际的间隔是多少:IP 地址范围?那么,您可能想要一个 Patricia trie,因为范围很可能是网络前缀。

标签: python performance dictionary


【解决方案1】:

如果您的区间是按升序排序的,您可以使用bisect 模块 (doc)。搜索是 O(log n) 而不是 O(n):

min_lst = [0,       4,       6]
max_lst = [3,       5,       6]
values = ['Hello', 'World', '!']

import bisect

val = 2

idx = bisect.bisect_left(max_lst, val)
if idx < len(max_lst) and min_lst[idx] <= val <= max_lst[idx]:
    print('Value found ->', values[idx])
else:
    print('Value not found')

打印:

Value found -> Hello

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 2011-07-02
    • 2021-12-07
    • 2017-10-27
    • 1970-01-01
    • 2019-03-14
    • 2020-08-09
    相关资源
    最近更新 更多