zoukankan      html  css  js  c++  java
  • numpy二分查找

        a = np.array([1, 2, 2, 3])
        print(np.searchsorted(a, 0))  # 0
        print(np.searchsorted(a, 1))  # 0
        print(np.searchsorted(a, 2))  # 1
        print(np.searchsorted(a, 2, 'left'))  # 1
        print(np.searchsorted(a, 2, 'right'))  # 3
        print(np.searchsorted(a, 2.5, 'right'))  # 3
        print(np.searchsorted(a, 2.5, 'left'))  # 3
        print(np.searchsorted(a, 3, 'left'))  # 3
        print(np.searchsorted(a, 3, 'right'))  # 4
        print(np.searchsorted(a, 4))  # 4
        print(np.searchsorted(a, [0, 1, 2, 3, 4, 5, ]))  # [0 0 1 3 4 4]
    

    searchsorted有三个重要参数:

    • a:待查找的有序数组
    • v:待查找的值
    • side:字符串,取值为left或者right,表示取下界(闭区间)还是取上界(开区间),默认参数为下界闭区间

    利用searchsorted可以非常炫酷地实现轮盘赌随机选取:

        t = np.cumsum(weights)
        sample = np.searchsorted(t, np.random.random() * t[-1])
    

    cumsum保证了递增,searchsorted二分查找,其中t[-1]表示全部元素之和,整个过程一气呵成、美不胜收。
    虽然如此,这种方式依然不是最好的方法。因为numpy提供了轮盘赌算法。

    from collections import Counter
    
    import numpy as np
    
    a = []
    for i in range(10000):
        x = np.random.choice([1, 2, 3], 2, p=[0.1, 0.3, 0.6])
        a.extend(x)
    a = Counter(a)
    a = np.array([np.array(i) for i in a.items()], dtype=np.float32)
    a[:, 1] /= np.sum(a[:, 1])
    print(a)
    
    

    输出为

    [[1.      0.0993 ]
     [2.      0.30325]
     [3.      0.59745]]
    

    因为searchsorted的下闭区间、上开区间效果有些奇特,所以可以wrap一下使它的行为更加明确

    二分查找实际上可以写成四种:

    • 左闭区间
    • 右闭区间
    • 左开区间
    • 右开区间

    如果自己写,一定要十分小心地考虑好边界条件才能够避免出错。

    import numpy as np
    
    
    def bisearch(a, v, can_eq=True, side='left'):
        x = np.searchsorted(a, v, side=side)
        if x >= a.shape[0]:
            return x
        if can_eq:
            if side == 'left':
                if a[x] == v:
                    return x
                else:
                    return x - 1
            else:
                if a[x] > v:
                    if x > 0 and a[x - 1] == v:
                        return x - 1
                    else:
                        return x
                else:
                    return x
        else:
            if side == 'left':
                if a[x] == v:
                    return x - 1
                else:
                    return x
            else:
                return x
    
    
    a = np.array([1, 2, 2, 4])
    print(bisearch(a, 2, True, 'left'))#1
    print(bisearch(a, 2, True, 'right'))#2
    print(bisearch(a, 2, False, 'left'))#0
    print(bisearch(a, 2, False, 'right'))#3
    print(bisearch(a, -1, True, 'left'))#-1
    print(bisearch(a, 5, True, 'right'))#4
    
    
  • 相关阅读:
    mongodb06---索引
    mongodb05---游标
    mongo04---基本查询
    mysql06---权限控制
    mysql05---游标
    使用 inotifywait的方式监控文件夹发生变化后自动执行脚本的方法
    ubuntu18.04 安装wine以及添加mono和gecko打开简单.net应用的方法
    Android之Socket群组聊天
    史上最完整的Android开发工具集合
    Android SurfaceView使用详解
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/9839157.html
Copyright © 2011-2022 走看看