【发布时间】:2019-10-30 07:52:30
【问题描述】:
如何用最短到最长匹配从头到尾替换文本
我有数据:
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)
感谢大家的回复,他们促成了这个缩短的版本
【问题讨论】:
-
所以,某些匹配项,例如
00 => '-------------------------------------'优先于某些其他匹配项000 => '-'? -
嗯,这是一个霍夫曼代码,所以二进制文件中没有重叠,唯一的问题是它必须从左到右替换,否则会有重叠。我希望有一种惯用的方法可以使用 itertools 或其他东西来解决这个问题,因为我的代码在工作时似乎不必要地迟钝。
-
@oppressionslayer 您帖子中的答案 sn-p 被混淆了,这使得它难以维护。我建议接受下面 RoyM 提供的答案,因为它更易于阅读和维护。
-
在这些方面这是最好的答案,我选择了它