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

如何加速Python中字符串权重组合的生成与求和?

问题:加速带权重组合的子串权重计算程序

我有一个字符串,其中部分字符存在备选权重,示例如下:

  • A(无权重选项)
  • S [27.0, 0]
  • D(无权重选项)
  • S [27.0, 0]
  • N [1.0, -20.0, 0]
  • P(无权重选项)

以字符串ASDSNP为例,每个S对应权重27.0和0.0,每个N对应权重1.0、-20.0和0.0等。我需要为给定字符串生成所有权重组合并计算其总和,每个字符串会根据权重组合得到多个权重和,并将不同字符串及其权重和存入字典。

目前我从长字符串中按规则生成大量子串,通过以下代码计算权重和,但运行耗时极长,已通过限制最大组合数max_totalcomb=2来控制组合爆炸,求加速程序的方法。

import itertools as it
import time
start_time=time.time()

def generate_substr(seq=None):
    for f in range(1,len(seq)):
        for g in range(1,len(seq)):
            if g >f :
                yield seq[f:g]

def wt_combinator(anystr=None,max_totalcomb = 2):
    '''
    Returns sum of a list of combinatorial modification weights
    '''
    wt_list=[]
    
    anystr = anystr.upper()
    wt_sites=char_wt.keys()

    for va in anystr:
        if va in wt_sites:
           wt_list.append(char_wt[va])

    wt_combination=list(it.product(*wt_list))
    filtered_combination=[e for e in wt_combination if 0 <= sum([int(bool(x)) for x in e]) <= max_totalcomb ]
    sumwt_list=[sum(cmb) for cmb in filtered_combination]
    if len(sumwt_list):
        return sumwt_list
    else:
        return [0]


char_wt= {   'N': [1.0, -20.0, 0],
             'Q': [1.0, 0],
             'S': [27.0, 0],
             'T': [27.0, 0],
             'Y': [27.0, 0]}
my_string = "MQIFVKTLTGKTITLEVEPSDTIENVKAKIQDKEGIPPDQQRLIFAGKQLEDGRTLSDYNIQKESTLHLVLRLRGG"

str_db = dict()
dbcounter = 0

for fseq in generate_substr(my_string):
    swt = wt_combinator(fseq)
    for w in swt:
        str_db[dbcounter]={'seq':fseq,'sumw':w}
        dbcounter +=1


end_time=time.time()
print(end_time - start_time)
print(len(str_db))
优化方案

1. 优化子串生成逻辑

原generate_substr函数中,g从1遍历到字符串长度再判断g>f,存在大量无效循环。直接让g从f+1开始遍历,省去多余判断:

def generate_substr(seq=None):
    seq_len = len(seq)
    for f in range(1, seq_len):
        # g直接从f+1起始,避免无效判断
        for g in range(f+1, seq_len):
            yield seq[f:g]

2. 避免全量组合生成,按需计算符合条件的权重和

原代码用it.product生成所有组合再过滤,是核心性能瓶颈。可以拆分权重选项,结合max_totalcomb限制直接生成有效组合:

# 预计算字符的非0权重和是否包含0选项
preprocessed_wt = {}
for char, wts in char_wt.items():
    non_zero = [w for w in wts if w != 0]
    has_zero = 0 in wts
    preprocessed_wt[char] = (non_zero, has_zero)

def wt_combinator(anystr=None, max_totalcomb=2):
    anystr = anystr.upper()
    non_zero_weights = []
    has_zero_list = []
    
    for char in anystr:
        data = preprocessed_wt.get(char)
        if not data:
            continue
        nz, has_zero = data
        non_zero_weights.append(nz)
        has_zero_list.append(has_zero)
    
    n = len(non_zero_weights)
    sumwt_list = []
    
    # 处理选0个非0权重的情况(所有可变字符都选0)
    if all(has_zero_list):
        sumwt_list.append(0.0)
    
    # 处理选1到max_totalcomb个非0权重的情况
    for k in range(1, min(max_totalcomb, n)+1):
        # 选择k个可变字符的位置
        for positions in it.combinations(range(n), k):
            # 未选中的位置必须能选0
            if all(has_zero_list[i] for i in range(n) if i not in positions):
                # 生成选中位置的非0权重组合
                selected = [non_zero_weights[i] for i in positions]
                for combo in it.product(*selected):
                    sumwt_list.append(sum(combo))
    
    # 去重减少重复存储(可选)
    sumwt_list = list(set(sumwt_list))
    return sumwt_list if sumwt_list else [0.0]

这种方式只生成符合max_totalcomb限制的组合,避免了全量组合的生成,能大幅降低计算量。

3. 优化存储结构

原代码用递增数字作为字典键存储每个(seq, sumw)对,可改用defaultdict将相同子串的权重和归类,减少字典操作开销:

from collections import defaultdict

str_db = defaultdict(list)
for fseq in generate_substr(my_string):
    swt = wt_combinator(fseq)
    str_db[fseq].extend(swt)

# 如需转换为原格式字典:
dbcounter = 0
final_db = {}
for seq, wts in str_db.items():
    for w in wts:
        final_db[dbcounter] = {'seq': seq, 'sumw': w}
        dbcounter += 1

4. 用生成器减少内存占用

在wt_combinator中改用生成器返回结果,避免一次性生成大列表占用内存,同时减少列表拷贝:

def wt_combinator(anystr=None, max_totalcomb=2):
    anystr = anystr.upper()
    non_zero_weights = []
    has_zero_list = []
    
    for char in anystr:
        data = preprocessed_wt.get(char)
        if not data:
            continue
        nz, has_zero = data
        non_zero_weights.append(nz)
        has_zero_list.append(has_zero)
    
    n = len(non_zero_weights)
    
    if all(has_zero_list):
        yield 0.0
    
    for k in range(1, min(max_totalcomb, n)+1):
        for positions in it.combinations(range(n), k):
            if all(has_zero_list[i] for i in range(n) if i not in positions):
                selected = [non_zero_weights[i] for i in positions]
                for combo in it.product(*selected):
                    yield sum(combo)

主循环中直接遍历生成器:

for fseq in generate_substr(my_string):
    for w in wt_combinator(fseq):
        str_db[dbcounter]={'seq':fseq,'sumw':w}
        dbcounter +=1

5. 并行处理(可选)

如果子串数量极大,可使用多进程并行计算每个子串的权重和,适合子串计算成本较高的场景:

from concurrent.futures import ProcessPoolExecutor

def process_subseq(subseq):
    return (subseq, list(wt_combinator(subseq)))

str_db = {}
dbcounter = 0

with ProcessPoolExecutor() as executor:
    for subseq, swts in executor.map(process_subseq, generate_substr(my_string)):
        for w in swts:
            str_db[dbcounter] = {'seq': subseq, 'sumw': w}
            dbcounter +=1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:40:18