Python之滑动窗口

摘要:
对于数组,array=[“n”,“v”,“l”,“f”,…,“y”,“c”,“k”];输入当前位置索引数组arraySize的长度基于当前位置。(前/后)滑动窗口windowSize中的元素数是滑动窗口的总长度:2*windowSize+1输出滑动窗口中元素的下标数组的形式为idx=3,arraySize=7,windowSzie=2=˃[1,2,3,4,5]idx=0,arraySize=7,windowSize=2=˃[5,6,0,1,2]idx=6,arraySiz=7,WindowSzie=2=˃[4,5,6,10]实现思想[1]循环队列[2]充分利用了模块化操作的特点:最左边的下标%arraySize和最后的下标%ArrySize可以计算源代码。使用想法2节省更多的计算资源。

需求

对于一个数组array = ["n","v","l","f",...,"y","c","k"];

  • input
    • 当前位置 index
    • 数组的长度 arraySize
    • 基于当前位置,(前/后)滑动窗口的元素数目 windowSize
      • 即 滑动窗口(假定:包含当前元素 array[idx]) 总长:2*windowSize+1
  • output
    • 滑动窗口中的元素下标数组
      • 形如
        • 【中间】idx=3,arraySize=7,windowSzie=2 => [1,2,3,4,5]
        • 【偏前】idx=0,arraySize=7,windowSzie=2 => [5,6,0,1,2]
        • 【偏后】idx=6,arraySize=7,windowSzie=2 => [4,5,6,1,0]

实现思路

  • [1] 循环队列
  • [2] 充分利用模运算的特点:最左边下标 (idx-windowSize)%arraySize 与 最后边下标(idx+windowSize)%arraySize可计算出来

源码 一

利用思路2,节省更多计算资源。
目前存在一种bug,比如 (2,10,3)

class CollectionUtil:
    def window(idx,arraySize,windowSize,containsCenterIdx=True): # 实现滑动窗口
        """
        获得当前位置的滑动窗口[元素的下标数组]
        -----------------------------------
        + idx : 当前位置下标
        + containsCenterIdx : 返回结果中,是否需要包含idex索引本身
        + 获得长为arraySize的列表中,以idex为中心,前后分别长windowSize个元素的的滑动窗口的元素下标数组
        + 默认数组下标最小为0
        + 滑动窗口总长 2*windowSize+1
        + 博文 [url] https://www.cnblogs.com/johnnyzen/p/10905958.html
        """
        if idx>=arraySize or idx < 0 or arraySize<1:
            raise ValueError("idx '",idx,"' out of arraySize '",arraySize,"' or them is error value!");
        if 2*windowSize+1 > arraySize:
            raise ValueError("2*windowSize+1 > arraySize! [ windowSize:",windowSize," | arraySize:",arraySize," ]");
        window = [];
        leftStart = (idx-windowSize)%(arraySize-1);  # 1,10,3 -> 7,8,9,0,1,2,3
        rightEnd = (idx+windowSize)%(arraySize-1);  # 9  0  1  2
        isRightWindowContinuous = True if idx+windowSize==rightEnd else False; # 判断右半窗口是否连贯
        for i in range(leftStart,leftStart + windowSize): # range(m,n) = [m,n)
            window.append(i);
            pass;
        if containsCenterIdx == True:
            window.append(idx);
        if isRightWindowContinuous == True:
            for i in range(rightEnd-windowSize+1,rightEnd+1): # 2-4+1
                window.append(i);
                pass;
        else : # 不连贯 即 右半窗口,一部分在数组开头,一部分在数组结尾
            for i in range(idx+1,arraySize-1+1):
                window.append(i);
                pass;
            for i in range(0,rightEnd):
                window.append(i);
                pass;
        return window;

测试

print(CollectionUtil.window(1,10,3)); # [7, 8, 9, 1, 2, 3, 4]
print(CollectionUtil.window(9,10,3)); # [6, 7, 8, 9, 0, 1, 2]
print(CollectionUtil.window(8,10,4)); # [4, 5, 6, 7, 8, 9, 0, 1, 2]
print(CollectionUtil.window(7,10,4)); # [3, 4, 5, 6, 7, 8, 9, 0, 1]
 # print(CollectionUtil.window(3,7,2)); # [1,2,3,4,5]
 # print(CollectionUtil.window(0,7,2)); # [5,6,0,1,2]
 # print(CollectionUtil.window(6,7,2)); # [4,5,6,0,1]

源码 二

利用循环队列,目前没有bug。

class CircularQueue: # 循环队列
    def __init__(self):
        self.queue = []*0; # 空列表
        self.cursor = 0;
    
    def push(self,eles):
        if isinstance(eles,Iterable) == True: # 可遍历类型  字符串("dsvvdsv")、列表、元组、字典、集合等
            for ele in eles:
                self.queue.append(ele);
            pass;
        else : # 其他,默认为 单元素处理
            self.queue.append(eles);
    
    def pop(self,index=-1):
        return self.queue.pop(index); # index=-1 : 移除最后一个元素
        pass;
    
    def index(self,obj):
        return self.queue.index(obj);

    def length(self):
        return len(self.queue);

    def next(self,idx=0):
        if idx >= len(self.queue)-1:
            return {"index":0,"value":self.queue[0]};
        else :
            return {"index":(idx+1),"value":self.queue[idx+1]};

    def prev(self,idx=0):
        if idx <=0:
            return {"index":(len(self.queue)-1),"value":self.queue[len(self.queue)-1]};
        else :
            return {"index":(idx-1),"value":self.queue[idx-1]};
    
    def print(self):
        print("queue:",self.queue);
    
    def window(self,idx,arraySize,windowSize): # 滑动窗口
        windowIndexs = [];
        for i in range(0,arraySize):
            self.push(i); # 初始化
            pass;
        nextNodeCursor = self.next(idx);  # 下一节点游标
        prevNodeCursor = self.prev(idx);  # 上一节点游标
        for i in range(0,windowSize): # 加载前窗口元素
            windowIndexs.append(prevNodeCursor["value"]);
            prevNodeCursor = self.prev(prevNodeCursor["index"]);
            # self.pop(nextNode["index"]);
            pass;
        windowIndexs.append(idx);
        for i in range(0,windowSize): # 加载后窗口元素
            windowIndexs.append(nextNodeCursor["value"]);
            nextNodeCursor = self.next(nextNodeCursor["index"]);
            # self.pop(prevNode["index"]);
            pass;
        windowIndexs.sort(); # 返回前 排序
        return windowIndexs;

测试

print("window:",CircularQueue().window(2,10,3)); # window: [0, 1, 2, 3, 4, 5, 9]

免责声明:文章转载自《Python之滑动窗口》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇高并发分布式锁docker进阶之路-基础篇 | 二:portainer安装与基本使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python学习——大文件分割与合并

在平常的生活中,我们会遇到下面这样的情况: 你下载了一个比较大型的游戏(假设有10G),现在想跟你的同学一起玩,你需要把这个游戏拷贝给他。 然后现在有一个问题是文件太大(我们不考虑你有移动硬盘什么的情况),假设现在只有一个2G或4G的优盘,该怎么办呢? 有很多方法,例如winrar压缩的时候分成很多小卷,这里不累述。 在学习python之后,我们自己就可以...

python实现labelme样本自动标注

python实现labelme样本自动标注 前言 说明 正文 一、 json文件简介及相关API: 二、 特征区域检测及相应API 三、 计算偏移量以及标注框的新的点集 四、 json文件数据其他修改 前言 公司前段时间做一个项目,需要用到语义分割,样本很多,但是都没有标注,也没有让标注公司弄,只好自己标注,平均两分半一张,一天标200多张...

使用 Python 和 Oracle 数据库实现高并发性

随着趋势发展的核心转向更多而不是更快发展,最大限度地提高并发性的重要性日益凸显。并发性使得编程模式发生了新的转变,可以编写异步代码,从而将多个任务分散到一组线程或进程中并行工作。如果您不是编程新手并且很熟悉 C 或 C++,您可能已经对线程和进程有所了解,并且知道它们之间的区别。在进行并发编程时,线程提供了进程的轻量级替代物,在大多数情况下多线程较多进程更...

关于Python的post请求报504错误

这是个奇葩的问题,我也是奇葩的研究了好几天,最后发现,哈,原来是这个原因,在此记录下曲折的心路历程 接口Content-Type没有,body用的是postman中的raw数据,格式是text 程序如下: importrequests url = "https://XXXXXX.com/api/user_device" headers = {...

Python小数向上取整和向下取整

Python小数向上取整和向下取整 首先需要导入math模块 import math 小数向上取整使用ceil函数 import mathf_num = 3.1 f_num = math.ceil(f_num) print(f_num) 小数向下取整使用floor函数 import math d_num = 3.9 d_num = math.floor...

Python基础知识

作者:地球的外星人君链接:https://www.zhihu.com/question/20336475/answer/197317130来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 1 算法 1.1 字符串 1.1.1 正则表达式 re 【标准库】 提供基于正则的匹配和替换。 1.1.2 字符集 chardet Home...