Skip to main content
 首页 » 编程设计

python之如何通过最短到最长的匹配从头到尾替换文本

2025年05月04日14yjmyzz

如何用最短到最长的匹配从头到尾替换文本

我有数据:

In [1807]: text='110011111000011010110011'                                                                                                                                                                  

和一个看起来像这样的字典:

s={'11': '++--', '01': '-+-+-', '000': '+-++++++', '001': '--', '100': '--+-', '101': '----++-+--'} 
 

我想将文本的输出替换为

'++----++--++--+-++++++-+-+-----++-+---+-+---+-++--' 

所以第一个 11,变为++--,第二个匹配是 001,然后是 --,第三个匹配是 11,然后被++-- 替换。最短的匹配项首先替换,但如果未找到,则替换第二长的匹配项。这必须从字符串的开头开始迭代,否则它不起作用。我正在寻找解决此问题的惯用方法。

我使用的当前代码有效,但我认为有更惯用的方法来解决这个问题。这是我目前拥有的:

 
s={'11': '++--', '01': '-+-+-', '000': '+-++++++', '001': '--', '100': '--+-', '101': '----++-+--'} 
 
peekstart=0 
peekend=1 
sptr='110011111000011010110011' 
bytestr=b'' 
while peekstart+peekend <= sptrlen: 
  match=False 
  while match == False: 
    peek = sptr[peekstart:peekstart+peekend]  
    findptr = s.get(peek) 
    while findptr == None: 
       peek = sptr[peekstart:peekstart+peekend+stream] 
       stream=stream+1 
       findptr = s.get(peek) 
    if stream == 0: 
      peekstart=peekstart+peekend+stream 
    else: 
      peekstart=peekstart+peekend+stream-1 
    stream=0 
    bytestr+=s.get(peek).encode() 
    match = True 
print(bytestr) 
b'++----++--++--+-++++++-+-+-----++-+---+-+---+-++--' 
 

有没有更惯用的方法来解决这个问题?

已回答

使用这里的答案,我想出了这个新版本,它可以很好地解压缩,并且不需要为以零开头的二进制文件提供缓冲区:

from functools import reduce 
s={'11': '++--', '01': '-+-+-', '000': '+-++++++', '001': '--', '100': '--+-', '101': '----++-+--'} 
 
def decompressHuffmanCode(a, bit): 
    return ('', a[1] + a[2][a[0]+bit[0]], a[2]) if (a[0]+bit[0] in a[2]) else (a[0]+bit[0], a[1], a[2]) 
 
# Added one to the front to deal with cases of the binary starting with zeroes 
compressed_binary='1110011111000011010110011' 
read_compressed_binary = compressed_binary[1:] 
remainder,bytestr,s = reduce(decompressHuffmanCode, read_compressed_binary, ('', '', s)) 
print(bytestr) 

感谢大家的回复,才有了这个精简版

请您参考如下方法:

这是一个常见的 eat-function。你从左边吃,直到你找到字典中匹配的东西。

text='110011111000011010110011' 
s={'11': '++--', '01': '-+-+-', '000': '+-++++++', '001': '--', '100': '--+-', '101': '----++-+--'} 
 
string = '' 
i = 0 
for j in range(len(text) + 1): 
    symbol = s.get(text[i:j]) 
    if symbol is not None: 
        string += symbol 
        i = j 
 
print(string) 

Out: ++----++--++--+-++++++-+-+-----++-+---+-+---+-++--