Python提取列表连续数字序列首尾元素问题求助
问题描述
我需要处理如下格式的有序整数列表:
[2,3,4,5,6,7,8,13,14,15,16,17,18,19,20,30,31,32,33,34,35]
最终目标是提取每个连续数字序列的首尾整数,得到结果:
[(2,8),(13,20),(30,35)]
作为Python新手,我尝试了以下代码:
helix = [] single_prot_helices = [] for ind,pos in enumerate(prot[:-1]): if pos == prot[ind+1]-1: # 判断当前数和下一个数是否连续 helix.append(pos) elif pos < prot[ind+1]-1: # 当前数和下一个数不连续 helix.append(pos) single_prot_helices.append(helix) # 保存临时列表到永久列表 helix.clear() # 清空临时列表
其中prot是上述示例格式的列表。我预期single_prot_helices的结果为:
[[2,3,4,5,6,7,8],[13,14,15,16,17,18,19,20],[30,31,32,33,34,35]]
但实际得到的结果却是:
[[20,30,31,32,33,34,35],[20,30,31,32,33,34,35]]
结果只保留了最后一个数字序列,且子列表数量比预期少1个(预期3个,实际2个)。我认为代码逻辑符合思路,但不清楚错误所在,希望得到帮助。
问题分析与解决方案
错误原因
- 列表引用传递问题:执行
single_prot_helices.append(helix)时,是把helix列表对象的引用加入永久列表,而非复制新列表。后续helix.clear()会修改所有引用该对象的内容,导致最终所有子列表都是最后一次修改后的结果。 - 循环范围遗漏:
prot[:-1]只遍历到倒数第二个元素,最后一个序列的末尾元素(比如示例中的35)未被处理,导致少一个子列表。 - 元素添加逻辑缺失:连续序列的末尾元素(比如示例中的8、20)未被加入临时列表,因为循环到前一个元素时只判断连续,没有把末尾元素加入。
修正后的代码
以下是修复问题后的代码,直接完成提取首尾元组的目标:
prot = [2,3,4,5,6,7,8,13,14,15,16,17,18,19,20,30,31,32,33,34,35] helix = [] single_prot_helices = [] for ind, pos in enumerate(prot): # 先把当前元素加入临时列表 helix.append(pos) # 不是最后一个元素时,检查下一个元素是否连续 if ind < len(prot) - 1: if pos != prot[ind+1] - 1: # 保存当前序列的副本,避免引用问题 single_prot_helices.append(list(helix)) helix.clear() # 循环结束后,加入最后一个剩余的序列 if helix: single_prot_helices.append(helix) # 提取每个子列表的首尾组成元组 result = [(seq[0], seq[-1]) for seq in single_prot_helices] print(result)
执行后会输出预期的[(2, 8), (13, 20), (30, 35)]。
更简洁的实现方式
可以用itertools.groupby简化代码,利用连续数的数值-索引为固定值的特性分组:
from itertools import groupby prot = [2,3,4,5,6,7,8,13,14,15,16,17,18,19,20,30,31,32,33,34,35] # 按"数值-索引"分组,连续的数该值相同 groups = groupby(enumerate(prot), key=lambda x: x[1] - x[0]) result = [] for _, group in groups: nums = [num for _, num in group] result.append((nums[0], nums[-1])) print(result)
内容的提问来源于stack exchange,提问作者plmnkndv
相关产品推荐
相关产品推荐

