如何从任意字符串/列表中提取指定大小的中心滑动窗口子序列
两类序列滑动窗口提取实现方案
常见的序列窗口提取分为两类场景:
- 从任意字符串中提取固定长度为n的连续窗口子串
- 给定元素列表,以列表中心位置为基准,向左右两侧各提取n个元素,生成符合尺寸要求的窗口子列表,遇到列表首尾边界时自动截断
列表中心窗口提取实现
先看给定的测试样例:
目标测试列表:
l = ['This', 'document', 'is', 'the', 'second', 'document']设置窗口参数
window=2(即中心元素左右各取2个元素),期望输出结果:['document', 'is', 'the', 'second', 'document']
原有实现代码存在两个核心问题,无法适配任意长度列表和窗口参数:
- 中心索引定位逻辑错误:使用
l.index(l[middle])查找中心位置时,如果列表存在重复元素,会返回第一个匹配元素的索引,和实际计算的中心位置产生偏移 - 未做窗口边界控制:直接拼接完整左半段和右半段列表,完全没有根据window参数限制截取长度,无法得到指定尺寸的窗口
正确实现逻辑非常直接,定位中心索引后通过切片边界控制截取范围即可:
- 用整数除法
len(lst) // 2计算中心索引,奇偶长度列表均可适配,无需额外类型转换 - 计算左边界:取
0和中心索引 - window的较大值,避免左边界超出列表起始位置 - 计算右边界:取
列表总长度和中心索引 + window + 1的较小值——由于Python切片为左闭右开规则,右边界需要额外+1才能覆盖到中心右侧第n个元素,同时避免超出列表末尾 - 直接按计算出的左右边界切片,即可得到目标子列表
可复用实现代码:
def get_center_window(lst: list, window: int) -> list: list_len = len(lst) center_idx = list_len // 2 left_bound = max(0, center_idx - window) right_bound = min(list_len, center_idx + window + 1) return lst[left_bound:right_bound] # 样例测试 l = ['This', 'document', 'is', 'the', 'second', 'document'] print(get_center_window(l, 2)) # 输出:['document', 'is', 'the', 'second', 'document']
该实现可自动适配边界场景:
- 当列表总长度小于
2*window +1时,会直接返回完整原列表,无下标越界问题 - 当window参数设为0时,仅返回中心位置的单个元素
- 奇数长度列表同样适用,例如长度为5的列表中心索引为2,window=1时会返回索引1、2、3对应的三个元素
字符串定长窗口子串提取
针对固定长度n的字符串窗口提取需求,遍历起始位置逐段切片即可,可按需选择是否保留末尾长度不足n的截断片段:
def get_fixed_length_substrings(s: str, n: int, keep_tail_truncated: bool = False) -> list: result = [] str_len = len(s) for start in range(str_len): end = start + n if end > str_len: if keep_tail_truncated: result.append(s[start:]) break result.append(s[start:end]) return result # 测试 test_str = "hello world" print(get_fixed_length_substrings(test_str, 3)) # 输出:['hel', 'ell', 'llo', 'lo ', 'o w', ' wo', 'wor', 'orl', 'rld']
内容的提问来源于stack exchange,提问作者tumbleweed
相关产品推荐
相关产品推荐

