You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中对列表内连续M对应数值求和(遇D中断)

合并连续M的数值并实现BAM软剪切转匹配

需求说明

你有若干按「数字+字母」顺序排列的列表,需要将连续出现的M对应的数值求和合并,遇到D则中断当前求和段,示例如下:
输入列表:

['20', 'M', '10', 'M', '1', 'D', '14', 'M', '106', 'M']
['124', 'M', '19', 'M', '7', 'M']
['19', 'M', '131', 'M']
['3', 'M', '19', 'M', '128', 'M']
['12', 'M', '138', 'M']

期望输出:

['30', 'M', '1', 'D', '120', 'M']
['150', 'M']
['150', 'M']
['150', 'M']
['150', 'M']

实际业务场景是将BAM文件中的软剪切(S)转为匹配(M),但卡在了数值合并步骤,现有代码片段如下:

#!/usr/bin/python

import sys 
import pysam

bamFile = sys.argv[1];

bam = pysam.AlignmentFile(bamFile, 'rb')

for read in bam:
    cigar=read.cigarstring
    sepa = re.findall('(\\d+|[A-Za-z]+)', cigar)
    
    for i in range(len(sepa)):
        if sepa[i] == 'S':
            sepa[i] = 'M'

解决方法

1. 核心合并逻辑

通过遍历拆分后的CIGAR列表,维护临时变量累积连续M的数值总和,遇到非M操作时先输出累积结果,再直接添加当前操作;遍历结束后处理剩余的M总和,实现合并逻辑:

def merge_consecutive_m(cigar_parts):
    result = []
    current_m_sum = 0
    # 按数字+字母的成对方式遍历
    for i in range(0, len(cigar_parts), 2):
        num = int(cigar_parts[i])
        op = cigar_parts[i+1]
        
        if op == 'M':
            current_m_sum += num
        else:
            # 先输出累积的M结果(如果有)
            if current_m_sum > 0:
                result.append(str(current_m_sum))
                result.append('M')
                current_m_sum = 0
            # 添加当前非M操作
            result.append(str(num))
            result.append(op)
    # 处理遍历结束后剩余的M总和
    if current_m_sum > 0:
        result.append(str(current_m_sum))
        result.append('M')
    return result

2. 整合到BAM处理代码中

将合并函数加入现有代码,补充缺失的模块导入,完成从S转M到合并连续M的完整流程:

#!/usr/bin/python

import sys 
import pysam
import re  # 补充导入re模块,原代码未导入但使用了re.findall

def merge_consecutive_m(cigar_parts):
    result = []
    current_m_sum = 0
    for i in range(0, len(cigar_parts), 2):
        num = int(cigar_parts[i])
        op = cigar_parts[i+1]
        
        if op == 'M':
            current_m_sum += num
        else:
            if current_m_sum > 0:
                result.append(str(current_m_sum))
                result.append('M')
                current_m_sum = 0
            result.append(str(num))
            result.append(op)
    if current_m_sum > 0:
        result.append(str(current_m_sum))
        result.append('M')
    return result

bamFile = sys.argv[1]

bam = pysam.AlignmentFile(bamFile, 'rb')

for read in bam:
    cigar = read.cigarstring
    sepa = re.findall('(\\d+|[A-Za-z]+)', cigar)
    
    # 将S替换为M
    for i in range(len(sepa)):
        if sepa[i] == 'S':
            sepa[i] = 'M'
    
    # 合并连续的M
    merged_cigar_parts = merge_consecutive_m(sepa)
    # 转为CIGAR字符串用于后续处理
    merged_cigar = ''.join(merged_cigar_parts)
    # 示例:输出处理后的CIGAR字符串,可根据需求调整逻辑(如写回BAM)
    print(merged_cigar)

bam.close()

代码说明

  • 补充re模块导入:原代码使用re.findall但未导入该模块,需补上。
  • 合并函数逻辑:按数字+操作符的成对结构遍历,精准处理连续M的累积与非M操作的中断输出。
  • 完整流程:完成CIGAR拆分、S转M、连续M合并的全链路处理,最终输出或复用处理后的CIGAR字符串。

内容的提问来源于stack exchange,提问作者fonpe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 23:05:32