【问题标题】:Binary-search without an explicit array没有显式数组的二进制搜索
【发布时间】:2019-06-29 01:20:31
【问题描述】:

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

在我的情况下,生成一个关于函数的值数组既不高效也不优雅。有什么方法可以实现吗?

【问题讨论】:

  • 您至少需要定义最大i。然后我认为编写自己的二进制搜索函数更容易/更简单。
  • 是的,函数是有界的,例如0
  • 也许您可以使用numpy 进行二分搜索,但您可能需要自己的类来实现实现collections.abc.Sequence 接口的动态序列。

标签: numpy binary-search


【解决方案1】:

类似的东西呢:

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]

这适用于np.searchsorted(),例如:

import numpy as np

gen_seq = GeneratorSequence(lambda x: x ** 2, 100)
np.searchsorted(gen_seq, 9)
# 3

你也可以编写自己的二分搜索函数,在这种情况下你并不真的需要 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

给出相同的结果:

all(bin_search(gen_seq, i) == np.searchsorted(gen_seq, i) for i in range(100))
# True

顺便说一句,这也WAY更快:

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

【讨论】:

  • 谢谢!这就是我要找的。​​span>
【解决方案2】:

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

def f(i):
    return i*2 # Just an example

class MySeq(Sequence):
    def __init__(self, f, maxi):
        self.maxi = maxi
        self.f = f
    def __getitem__(self, x):
        if x < 0 or x > self.maxi:
             raise IndexError()
        return self.f(x)
    def __len__(self):
        return self.maxi + 1

在这种情况下,f 是您的函数,而 maxi 是最大索引。这当然只有在函数 f 以排序顺序返回值时才有效。
此时您可以在np.searchsorted 中使用MySeq 类型的对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    相关资源
    最近更新 更多