繁体   English   中英

为什么 python 的“二分法”模块(二进制搜索)不允许将其与特定的“键”一起使用?

[英]Why python's 'bisect' module (binary search) does not allow use it with particular 'key'?

引用文档:

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

与 sorted() function 不同,bisect() 函数具有键或反转 arguments 是没有意义的,因为这会导致设计效率低下(连续调用 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 没有呢? (假设标语“包含电池”)

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

从 Python 3.10 开始, bisect模块中的所有二进制搜索助手都接受一个key参数。 例如,关于bisect_left的文档包含以下内容:

key指定一个参数的键 function ,用于从数组中的每个元素中提取比较键。 为了支持搜索复杂记录,键 function 未应用于x值。

如果 key 是None ,则直接比较元素而不进行干预 function 调用。

因此,您可以像sorted()一样使用此参数。 请注意,根据操作的不同,键 function 可能不会应用于要搜索的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM