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

如何实现按括号层级拆分数学表达式的breakInChunks函数并修复输出异常

程序说明

需要实现breakInChunks()函数,该函数接收1个参数temp_s: string,temp_s为数学表达式,例如1+(3-e^(x-6))-8+(99-4)*10。函数需要识别左、右括号,将括号内的表达式替换为格式为[i$j]的块(i为左括号下标,j为右括号下标)。若某个完整块[m$n]内部包含多个子块,程序需要将m到n区间的字符整体替换为[m$n]。最终函数返回keypairs字典,键为块标识,值为从原始字符串中截取的对应内容,例如{'23$28': 'string within 23 and 28 characters'}。所有括号外的剩余字符也需要按相同的块:字符串格式追加到字典末尾。

输入输出示例
  • 输入示例:(7+x+8*(9+10(11+12)+14))-(2*(34))
  • 输出示例:
{'12$18': '11+12', '7$22': '9+10[12$18]+14', '0$23': '7+x+8*[7$22]', '28$31': '34', '25$32': '2*[28$31]', '24:25': '-'}
问题描述

处理更复杂的字符串时返回结果异常,示例如下:
输入:

(7+y+(66+7)+(32+(78*19-(32-0)))+(32-9))+8+9+(9-10)-(9/7)-10

异常输出:

{'5$10': '66+7', '23$28': '32-0', '16$29': '78*19-[23$28', '12$30': 
'32+[16$29]))+8+9+', '32$37': '32-9', '0$38': '7+y+(66+7)+(32+[16$29][23$28]]37]])+8',
'44$49': '9-10', '51$55': '9/7', '11:0': '', '31:0': '', '39:44': '+8+9+', '50:51': '-',
}

具体表现:当一个块内部包含多个独立子块时,程序会将多个子块内容错误拼接,无法正确返回单个外层块。

现有代码
def findall(sstr, substr):
    gen = sstr.find(substr)
    while gen != -1:
        yield gen
        gen = sstr.find(substr, gen + 1)


def findclosest(l: list, el: list):  # find closest string from L to string from EL
    j = el[ 1 ]
    minimum = j
    min_index = 0
    for i in range(len(l)):
        if l[ i ][ 0 ] - j < minimum:
            minimum = l[ i ][ 0 ] - j
            min_index = l[ i ][ 0 ]
    return min_index


def breakInChunks(temp_s):  # main
    list_of_additions = [ ]
    list_of_opened = list(findall(temp_s, '('))
    list_of_closed = list(findall(temp_s, ')'))
    if sum(list_of_opened) < sum(list_of_closed) and len(list_of_opened) == len(
            list_of_closed):
        n = 0
        # <WHILE>
        while len(
                list_of_closed) != 0:  # read strings-expressions from the most inner ones to the most outer ones
            minimum = list_of_closed[ len(list_of_closed) - 1 ]
            j = list_of_closed.pop(0)
            for i in range(len(list_of_opened)):  # find the closest opening bracket to the most inner closing one
                diff = j - list_of_opened[ i ]
                if diff > 0:
                    if diff <= minimum:
                        pop_index = i
                        minimum = j - list_of_opened[ i ]
                else:
                    break
            starting_index = list_of_opened.pop(pop_index)
            # start filling KEYPAIRS
            if len(keypairs) == 0:  # if KEYPAIRS is empty
                keypairs[ f'{starting_index}${j}' ] = temp_s[ starting_index + 1:j ]
            else:  # if KEYPAIRS has at least one key-value pair
                keys = [ key.split('$') for key in
                         keypairs.keys() ]  # reading and unpacking key-value pairs (reading indecies)
                innerSeq = temp_s
                min_index_i = None
                min_index_j = None
                prevExtracted_i = 0
                prevExtracted_j = 0
                for p in range(len(keys) - 1, -1, -1):
                    k = keys[ p ]
                    extracted_i, extracted_j = int(k[ 0 ]), int(k[ 1 ])
                    if starting_index < extracted_i:  # if the chunk we are checking contains another one, we are checking if it's in fact the closest one to the chunk we are checking
                        if (
                                extracted_i < prevExtracted_i and prevExtracted_j < extracted_j) or prevExtracted_i == 0:
                            min_index_i = extracted_i
                            min_index_j = extracted_j
                            if prevExtracted_i == 0:
                                if extracted_i > int(keys[ p - 1 ][ 0 ]) and extracted_j < int(keys[ p - 1 ][ 1 ]):
                                    pass
                                else:
                                    innerSeq = innerSeq[
                                               :extracted_i ] + f'[{extracted_i}${extracted_j}]' + innerSeq[
                                                                                                   extracted_j + 1: ]
                        else:
                            if min_index_i is not None:
                                innerSeq = innerSeq[ :min_index_i ] + f'[{min_index_i}${min_index_j}]' + innerSeq[
                                                                                                         min_index_j + 1: ]
                                min_index_i = None
                                min_index_j = None
                            else:
                                innerSeq = innerSeq[
                                           :prevExtracted_i ] + f'[{prevExtracted_i}${prevExtracted_j}]' + innerSeq[
                                                                                                           prevExtracted_j + 1: ]
    
                        prevExtracted_i = extracted_i
                        prevExtracted_j = extracted_j
                        n += 1
    
                keypairs[ f'{starting_index}${j}' ] = innerSeq[ starting_index + 1:j ]
    
        # </WHILE>
    
        # checking if there are any strings outside parentheses left
        temp = [ [ int(key.split('$')[ 0 ]), int(key.split('$')[ 1 ]) ] for key in sorted(keypairs.keys(),
                                                                                          key=lambda el: int(
                                                                                              el.split('$')[1])) ]  # sort from the most inner to the most outer
        for i in range(len(temp) - 1):
            if temp[ i ][ 1 ] < temp[ i + 1 ][
                0 ]:  # if there is a gap between parentheses
                # find the closest difference in order to find actual string outside chunks with the help of findclosest()
                # add new chunk to LIST_OF_ADDITIONS
                list_of_additions.append([ temp[ i ][ 1 ] + 1, findclosest(temp[ i + 1: ], temp[ i ]) ])
    
        if len(list_of_additions) > 0:  # if something is inside LIST_OF_ADDITIONS
            # add remaining strings to KEYPAIRS
            for addition in list_of_additions:
                keypairs[ f'{addition[ 0 ]}:{addition[ 1 ]}' ] = self.s[ addition[ 0 ]:addition[ 1 ] ]
    
        return keypairs  # return KEYPAIRS
    else:
        raise RuntimeError(f'Amount of closing and opening brackets does not match')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 02:06:00