【问题标题】:Why python's 'bisect' module (binary search) does not allow use it with particular 'key'?为什么 python 的 'bisect' 模块(二进制搜索)不允许将它与特定的 'key' 一起使用?
【发布时间】:2020-01-24 23:03:04
【问题描述】:

引用自文档:

https://docs.python.org/3/library/bisect.html

与 sorted() 函数不同,它对 bisect() 没有意义 具有关键或反向参数的函数,因为这会导致 低效的设计(连续调用 bisect 函数不会 “记住”之前的所有键查找)。

相反,最好搜索预先计算的键列表以找到 相关记录的索引:

>>> data = [('red', 5), ('blue', 1), ('yellow', 8), ('black', 0)]
>>> data.sort(key=lambda r: r[1])
>>> keys = [r[1] for r in data]         # precomputed list of keys
>>> data[bisect_left(keys, 0)]
('black', 0)

但建议的解决方案适用于O(N)(创建键列表),不适用于O(logN)(假设需要为一个列表调用一次 bisect)。

是否有任何内置的二进制搜索,允许使用自定义键进行搜索?

(除了为传递的对象重载operator __lt__()。)

如果没有,那为什么 python 没有呢? (假设标语“包括电池”)

【问题讨论】:

  • 标语“包括电池”不能意味着“包括所有可能的东西”,因为有无限可能的东西

标签: python python-3.x binary-search


【解决方案1】:

bisectinsort 的参数可能不一致,或者您必须传递一个值而不是键来进行搜索。无论哪种方式,某人都会遭遇不幸的意外。

也就是说,要么

def insort(a, x, lo=0, hi=None, *, key=None):
    lo = bisect(a, x, lo, hi, key)
    a.insert(lo, x)

def bisect(a, x, lo=0, hi=None, *, key=None):
    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    if key is None:
        key = lambda x: x
    while lo < hi:
        mid = (lo+hi)//2
        if key(x) < key(a[mid]): hi = mid
        else: lo = mid+1
    return lo

>>> key=lambda r: r[1]
>>> insort(data, ('green', 3), key=key)
>>> bisect(data, 7, key=key) # error comparing tuple to int

或者

def insort(a, x, lo=0, hi=None, *, key=None):
    if key is None:
        key = lambda x: x
    lo = bisect(a, key(x), lo, hi, key)
    a.insert(lo, x)

def bisect(a, x, lo=0, hi=None, *, key=None):
    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    if key is None:
        key = lambda x: x
    while lo < hi:
        mid = (lo+hi)//2
        if x < key(a[mid]): hi = mid
        else: lo = mid+1
    return lo

>>> key=lambda r: r[1]
>>> item = ('green', 3)
>>> insort(data, item, key=key)
>>> bisect(data, item, key=key) # error comparing int to tuple

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 2023-02-05
    • 1970-01-01
    • 2011-05-09
    • 2017-10-27
    • 2014-12-09
    • 1970-01-01
    相关资源
    最近更新 更多