Numpy 无显式数组的二进制搜索

Numpy 无显式数组的二进制搜索,numpy,binary-search,Numpy,Binary Search,我想使用例如np.searchsorted执行二进制搜索,但是,我不想创建包含值的显式数组。相反,我想定义一个函数,给出在数组的所需位置预期的值,例如p(I)=I,其中I表示数组中的位置 在我的例子中,生成一个关于函数的值数组既不高效也不优雅。有什么方法可以做到这一点吗?受@norok2 comment的启发,我认为您可以使用以下内容: def(i): return i*2#只是一个例子 类MySeq(序列): 定义初始化(self,f,maxi): self.maxi=maxi self.f=

我想使用例如
np.searchsorted
执行二进制搜索,但是,我不想创建包含值的显式数组。相反,我想定义一个函数,给出在数组的所需位置预期的值,例如
p(I)=I
,其中I表示数组中的位置


在我的例子中,生成一个关于函数的值数组既不高效也不优雅。有什么方法可以做到这一点吗?

受@norok2 comment的启发,我认为您可以使用以下内容:

def(i):
return i*2#只是一个例子
类MySeq(序列):
定义初始化(self,f,maxi):
self.maxi=maxi
self.f=f
定义获取项目(self,x):
如果x<0或x>self.maxi:
提升索引器()
返回self.f(x)
定义(自我):
返回self.maxi+1
在这种情况下,
f
是您的函数,而
maxi
是最大索引。当然,这仅在函数
f
按排序顺序返回值时有效。

此时,您可以在
np中使用
MySeq
类型的对象

import collections

class GeneratorSequence(collections.Sequence):
    def __init__(self, func, size):
        self._func = func
        self._len = size

    def __len__(self):
        return self._len

    def __getitem__(self, i):
        if 0 <= i < self._len:
            return self._func(i)
        else:
            raise IndexError

    def __iter__(self):
        for i in range(self._len):
            yield self[i]

您也可以编写自己的二进制搜索函数,在这种情况下,您并不真正需要NumPy,它实际上是有益的:

def bin_search(seq, item):
    first = 0
    last = len(seq) - 1
    found = False
    while first <= last and not found:
        midpoint = (first + last) // 2
        if seq[midpoint] == item:
            first = midpoint
            found = True
        else:
            if item < seq[midpoint]:
                last = midpoint - 1
            else:
                first = midpoint + 1
    return first
顺便说一句,这也是更快的方式:

gen_seq = GeneratorSequence(lambda x: x ** 2, 1000000)

%timeit np.searchsorted(gen_seq, 10000)
# 1 loop, best of 3: 1.23 s per loop
%timeit bin_search(gen_seq, 10000)
# 100000 loops, best of 3: 16.1 µs per loop

您至少需要定义最大
i
。然后我认为编写自己的二进制搜索函数更容易/更简单。是的,函数将是有界的,例如0也许您可以使用
numpy
进行二进制搜索,但是您可能需要自己的类实现一个动态序列,实现
collections.abc.sequence
接口。谢谢!这就是我要找的。
all(bin_search(gen_seq, i) == np.searchsorted(gen_seq, i) for i in range(100))
# True
gen_seq = GeneratorSequence(lambda x: x ** 2, 1000000)

%timeit np.searchsorted(gen_seq, 10000)
# 1 loop, best of 3: 1.23 s per loop
%timeit bin_search(gen_seq, 10000)
# 100000 loops, best of 3: 16.1 µs per loop