python bisect 二分算法工具以及应用

python bisect 工具以及应用
主要用于在顺序固定的序列中查找以及插入

内置了四种方法

  • bisect_left
  • bisect_right
  • insort_right
  • insort_left

bisect_left/right 方法找到应该插入元素的位置,对于和序列中元素不相同的值,两个方法返回的一样,对于相同的值,left返回相同值的位置,right返回相同值下一个位置
例如在ps = [1, 3, 5, 9, 9, 100]
query = 9
的话,left返回3,right返回5

import bisect
import pandas as pd
import numpy as np
from functools import reduce
from typing import List

import tensorflow as tf
import torch
from sklearn.preprocessing import KBinsDiscretizer


# Bisection algorithms. 源码阅读
def insort_right(a, x, lo=0, hi=None, *, key=None):
    """Insert item x in list a, and keep it sorted assuming a is sorted.
    If x is already in a, insert it to the right of the rightmost x.
    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    A custom key function can be supplied to customize the sort order.
    """
    if key is None:
        lo = bisect_right(a, x, lo, hi)
    else:
        lo = bisect_right(a, key(x), lo, hi, key=key)
    a.insert(lo, x)


def insort_left(a, x, lo=0, hi=None, *, key=None):
    """Insert item x in list a, and keep it sorted assuming a is sorted.
    If x is already in a, insert it to the left of the leftmost x.
    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    A custom key function can be supplied to customize the sort order.
    """
    if key is None:
        lo = bisect_left(a, x, lo, hi)
    else:
        lo = bisect_left(a, key(x), lo, hi, key=key)
    a.insert(lo, x)


def bisect_right(a, x, lo=0, hi=None, *, key=None):
    """Return the index where to insert item x in list a, assuming a is sorted.
    The return value i is such that all e in a[:i] have e <= x, and all e in
    a[i:] have e > x.  So if x already appears in the list, a.insert(i, x) will
    insert just after the rightmost x already there.
    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    A custom key function can be supplied to customize the sort order.
    """
    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    # Note, the comparison uses "<" to match the
    # __lt__() logic in list.sort() and in heapq.
    if key is None:
        while lo < hi:
            mid = (lo + hi) // 2
            if x < a[mid]:
                hi = mid
            else:
                lo = mid + 1
    else:
        while lo < hi:
            mid = (lo + hi) // 2
            if x < key(a[mid]):
                hi = mid
            else:
                lo = mid + 1
    return lo


def bisect_left(a, x, lo=0, hi=None, *, key=None):
    """Return the index where to insert item x in list a, assuming a is sorted。
    The return value i is such that all e in a[:i] have e < x, and all e in
    a[i:] have e >= x.  So if x already appears in the list, a.insert(i, x) will
    insert just before the leftmost x already there.
    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    A custom key function can be supplied to customize the sort order.
    """
    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    # Note, the comparison uses "<" to match the
    # __lt__() logic in list.sort() and in heapq.
    if key is None:
        while lo < hi:
            mid = (lo + hi) // 2
            if a[mid] < x:
                lo = mid + 1
            else:
                hi = mid
    else:
        while lo < hi:
            mid = (lo + hi) // 2
            if key(a[mid]) < x:
                lo = mid + 1
            else:
                hi = mid
    return lo


# Application
# 二分查找函数
ps = [1, 3, 5, 9, 100]
T = 66
print(bisect.bisect_left(ps, T, lo=0, hi=len(ps)))  # 二分左边界
print(bisect.bisect_right(ps, T, lo=0, hi=len(ps)))  # 二分右边界
print(bisect.bisect_left(ps, 9, lo=0, hi=len(ps)))  # 二分左边界
print(bisect.bisect_right(ps, 9, lo=0, hi=len(ps)))  # 二分右边界
bisect.insort_left(ps, T, lo=0, hi=len(ps))  # 二分插入到左侧
bisect.insort_right(ps, T, lo=0, hi=len(ps))  # 二分插入到右侧


# 当时自我实现的,找到右边第一个比target的大的值的位置
def find_next_greater_o(arr, target):
    """相当于bisect_right"""
    low, high = 0, len(arr) - 1
    try:
        if target < arr[low]:
            return -1
    except Exception as e:
        return -1

    while low <= high:
        mid = low + (high - low) // 2
        if arr[mid] <= target:
            low = mid + 1
        else:
            if arr[mid - 1] <= target:
                return mid
            high = mid - 1
    return -1


# 利用bisect实现
def find_next_greater(arr, target):
    try:
        i = bisect_right(arr, target, lo=0, hi=len(arr))
        if i == len(arr):
            return -1
        return i
    except Exception as e:
        print(f"Error [{e}] happened when finding the [{target}], return default")
        return -1


def find_gt(a, x):
    # Find leftmost value greater than
    i = bisect_right(a, x)
    if i != len(a):
        return i
    return -1


arr = [3, 4, 6, 7]
target = 5


# print(find_next_greater(arr, target))
# print(find_gt(arr, target))
# print(find_next_greater(arr, 'fd'))
# print(find_next_greater(arr, 999))
# print(find_gt(arr, 999))

# def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
#     i = bisect(breakpoints, score)
#     return grades[i]
#
# a = [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
# ['F', 'A', 'C', 'C', 'B', 'A', 'A']

应用:数据分箱

# 数据分箱
def p_cut(bins: List[int], val: int, grades=None) -> int:
    """
    return the result of discretization input val;左闭右开;
    :param bins: bins for describe
    :param val: value to set
    :param grades: customize the output
    """
    if grades is not None:
        assert len(bins) == len(grades)
        grades = grades
    else:
        grades = reduce(lambda x, y: str(x) + str(y),
                        [i for i in range(len(bins) + 1)])

    # try if for cover typeerror
    try:
        i = bisect_right(bins, val)
        return int(grades[i])
    except TypeError as e:
        print(f"TypeError: {e} for input {val}")
        return -1

print("*" * 10 + "Discretization test" + "*" * 10)
print(p_cut([1, 10, 20, 50, 100], val=5))
print(p_cut([1, 10, 20, 50, 100], val=1))
print(p_cut([1, 10, 20, 50, 100], val=10))
print(p_cut([1, 10, 20, 50, 100], val=500))
print(p_cut([1, 10, 20, 50, 100], val=""))

bins = [1, 10, 20, 50, 100]
test_arr = [-100, None, 1, 5, 30, 500]
test_arr1 = [-100, 1, 5, 30, 500]
print([p_cut(bins, v) for v in test_arr])

# 同样的功能利用pandas cut实现
# pandas cut 不支持val是其他类型,会直接报typeerror;
# pandas cut 对于不在区间内的值做NaN处理
print(pd.cut(test_arr1, bins=bins, labels=['a', 'b', 'c', 'd']))

# 在大数据情况下,pandas cut可能不够高效,同样的功能还可以使用sklearn实现
data = np.array(test_arr1).reshape(-1, 1)  # 重塑数据为2D,因为 Scikit-Learn 需要2D数组
est = KBinsDiscretizer(n_bins=4, encode='ordinal', strategy='quantile')
est.fit(data)
bins_sk = est.bin_edges_[0]  # 获取边界
print(bins_sk)

# tensorflow实现
## tf.keras.layers.Discretization
## tf.keras.layers.Discretization 左闭右开
"""在tf1 中是使用 tf.feature_column.bucketized_column
但是在tf2 中官方推荐的是tf.keras.layers.Discretization
"""
discretization_layer = tf.keras.layers.Discretization(bin_boundaries=bins)
print(f"tf.keras output:{discretization_layer(test_arr1)}")

## tf.searchsorted or torch.searchsorted(bins, values, right=True) 左开右闭
print(tf.reshape(tf.searchsorted(bins, test_arr1), (-1, len(test_arr1))))

bins_tensor = torch.tensor(bins, dtype=torch.float32)
values = torch.tensor(test_arr1, dtype=torch.float32)
indices = torch.searchsorted(bins_tensor, values, right=False)

# 对比
print("*" * 10)
print(f"self code output:{[p_cut(bins, v) for v in test_arr1]}")
print(f"pd.cut output: {pd.cut(test_arr1, bins=bins)}")
print(f"tf.keras output:{discretization_layer(test_arr1)}")
print(f"torch.searchsorted output:{indices}")
print(f"tf.searchsorted output :{tf.searchsorted(bins, test_arr1)}")
print("*" * 10 + "Discretization test finished" + "*" * 10) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/600430.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Dell EMC Storage Unity: Remove/Install Memory Module

SP A 一个内存故障 点击system view -> Enclosures->Top查看 再次查看Alert&#xff0c; 确认内存出现问题 进入Service &#xff0c; 将SP A置为service状态 移出SP A &#xff0c;进行内存更换 更换完内存后&#xff0c;将SP A插入设备&#xff0c;并进行线缆连接 进入…

了解 Postman:这个 API 工具的功能和用途是什么?

在软件开发中&#xff0c;经常听到 Postman 这个软件名。但其实很多新手开发者只知道这是软件开发常用的软件&#xff0c;并不知道实际是一个什么样工具&#xff0c;不知道具体的作用是什么。那今天就跟大家好好唠唠 Postman 这个软件。想要学习更多关于 Postman 的知识&#x…

洛谷 P3391:文艺平衡树 ← Splay树模板题

【题目来源】https://www.luogu.com.cn/problem/P3391【题目描述】 您需要写一种数据结构&#xff08;可参考题目标题&#xff09;&#xff0c;来维护一个有序数列。 其中需要提供以下操作&#xff1a;翻转一个区间&#xff0c;例如原有序序列是 5 4 3 2 1&#xff0c;翻转区间…

分布式任务调度工具 XXL-JOB

默认的账号密码是&#xff1a;admin/123456 一&#xff0c;部署docker容器 docker run \ -e PARAMS"--spring.datasource.urljdbc:mysql://192.168.150.101:3306/xxl_job?Unicodetrue&characterEncodingUTF-8 \ --spring.datasource.usernameroot \ --spring.dataso…

【刷题篇】双指针(一)

文章目录 1、移动零2、复写零3、快乐数4、盛最多水的容器 1、移动零 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 class Solution { pub…

区间预测——conformal tights

conformal tights 是一个python包 特征&#xff1a; sklearn元估计器&#xff1a;向任何scikit-learn回归器添加分位数和区间的共形预测 darts预测&#xff1a;向任何scikit-learn回归器添加共形校准的概率预测 保形校准&#xff1a;准确的分位数和可靠的覆盖的区间 相干分…

开源go实现的iot物联网新基建平台

软件介绍 Magistrala IoT平台是由Abstract Machines公司开发的创新基础设施解决方案&#xff0c;旨在帮助组织和开发者构建安全、可扩展和创新的物联网应用程序。曾经被称为Mainflux的平台&#xff0c;现在已经开源&#xff0c;并在国际物联网领域受到广泛关注。 功能描述 多协…

数据结构——链表专题3

文章目录 一、判断链表是否有环二、返回入环的第一个节点三、随机链表的复制 一、判断链表是否有环 原题链接&#xff1a;判断链表是否有环 这道题可以使用快慢指针&#xff0c;fast一次走两步&#xff0c;slow一次走一步&#xff0c;如果有环&#xff0c;它们在环里面必定会…

Java 框架安全:Spring 漏洞序列.(CVE-2022-22965)

什么叫 Spring 框架. Spring 框架是一个用于构建企业级应用程序的开源框架。它提供了一种全面的编程和配置模型&#xff0c;可以简化应用程序的开发过程。Spring 框架的核心特性包括依赖注入&#xff08;Dependency Injection&#xff09;、面向切面编程&#xff08;Aspect-Or…

TCP经典异常问题探讨与解决

作者&#xff1a;kernelxing TCP的经典异常问题无非就是丢包和连接中断&#xff0c;在这里我打算与各位聊一聊TCP的RST到底是什么&#xff1f;现网中的RST问题有哪些模样&#xff1f;我们如何去应对、解决&#xff1f;本文将从RST原理、排查手段、现网痛难点案例三个板块自上而…

【Linux系列】file命令

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

yum仓库和NFS网络共享服务

一、yum 1.1yum的定义 yum是一个基于RPM包&#xff0c;构建的软件更新机制&#xff0c;能够自动解决软件包之间的依赖关系。解决了日常工作中的大量查找安装依赖包的时间 为什么会有依赖关系的发生 因为linux本身就是以系统简洁为自身优势&#xff0c;所以在安装操作系统的时…

DB-GPT: Empowering Database Interactions with Private Large Language Models 导读

本文介绍了一种名为DB-GPT的新技术&#xff0c;它将大型语言模型&#xff08;LLM&#xff09;与传统数据库系统相结合&#xff0c;提高了用户使用数据库的体验和便利性。DB-GPT可以理解自然语言查询、提供上下文感知的回答&#xff0c;并生成高准确度的复杂SQL查询&#xff0c;…

搭建父模块和工具子模块

第一章 项目父模块搭建 1.1 nancal-idsa 作为所有工程的父工程&#xff0c;用于管理项目的所有依赖版本。 1.2 指定 pom 类型模块&#xff0c;删除 src 目录&#xff0c;点击Reload project 1.3 添加依赖 pom.xml <parent> <groupId>org.springframework.…

鸿蒙内核源码分析(中断管理篇) | 江湖从此不再怕中断

关于中断部分系列篇将用三篇详细说明整个过程. 中断概念篇 中断概念很多&#xff0c;比如中断控制器&#xff0c;中断源&#xff0c;中断向量&#xff0c;中断共享&#xff0c;中断处理程序等等.本篇做一次整理.先了解透概念才好理解中断过程.用海公公打比方说明白中断各个概念…

端口被其他进程占用:OSError: [Errno 98] Address already in use

一、问题描述 错误提示端口号正在被使用 二、解决办法 1.使用 lsof 命令&#xff0c;列出所有正在监听&#xff08;即被绑定&#xff09;的网络连接&#xff0c;包括它们所使用的端口号 sudo lsof -i -P -n | grep LISTEN 2.解绑被绑定的端口号 根据 netstat 或 lsof 命令…

基于OpenPCDet框架进行Pointpillars算法环境搭建并基于TensorRT和ROS部署

文章目录 参考链接1.创建虚拟环境2.安装OpenDet3.安装用于模型转换的库4.数据集转换5.模型训练6.部署安装tensorrt模型转换 编译ROS工程结果报错梳理【报错1】【报错2】【报错3】【报错4】【报错5】 参考链接 基于OpenDet进行训练&#xff0c;基于tensorrt-8.5进行部署并移植到…

常见错误以及如何纠正它们

团队和关键结果目标 (OKR) 之间的关系是深刻且至关重要的。总而言之&#xff0c;一切都应该是相互关联的。正如《团队的智慧》一书中所强调的&#xff1a; 在团队中&#xff0c;没有什么比每个成员对共同目标和一组相关绩效目标的承诺更重要的了&#xff0c;而团队对此负有共同…

经常发文章的你是否想过定时发布是咋实现的?

前言 可乐他们团队最近在做一个文章社区平台,由于人手不够,前后端都是由前端同学来写。后端使用 nest 来实现。 某一天周五下午,可乐正在快乐摸鱼,想到周末即将来临,十分开心。然而,产品突然找到了他,说道:可乐,我们要做一个文章定时发布功能。 现在我先为你解释一…

值得收藏!修复Windows 10/11中找不到输出或输入设备的五种方法

序言 这篇文章主要关注处理声音输出/输入设备未发现的问题。它提供了许多可行的方法,帮助了许多Windows用户。阅读以下内容以找到你的解决方案。 最近,我将Windows 10更新到21H2,发现我的音频无法工作。当我把鼠标放在任务栏上的声音图标(上面有一个十字图标)上时,它会…