Python中的字符串覆盖优化

5 投票
6 回答
642 浏览
提问于 2025-04-16 07:02

我有一个初始字符串。

'bananaappleorangestrawberryapplepear'

还有一个包含字符串的元组:

('apple', 'plepe', 'leoran', 'lemon')

我想要一个函数,能够根据这个初始字符串和元组里的字符串,得到这个结果:

'bananaxxxxxxxxxgestrawberryxxxxxxxar'

我知道怎么用一种比较直接的方法来做,就是在初始字符串中找到每个单词,然后逐个字符地遍历整个初始字符串,替换掉找到的单词。

不过这样做效率不高,而且看起来也不太好。我觉得应该有更优雅的方法,可以用函数式编程的方式,可能用到 itertools 或者其他的工具。如果你知道有什么 Python 库可以高效地做到这一点,请告诉我。

更新:Justin Peel 提到了一种我在最初问题中没有描述的情况。如果一个单词是 'aaa',而初始字符串中有 'aaaaaa',那么输出应该是 'xxxxxx'。

6 个回答

1

这里有另一个答案。可能有更快的方法来把字母替换成x,但我觉得这样已经够快了,不需要再改了。

import re

def do_xs(s,pats):
    pat = re.compile('('+'|'.join(pats)+')')

    sout = list(s)
    i = 0
    match = pat.search(s)
    while match:
        span = match.span()
        sout[span[0]:span[1]] = ['x']*(span[1]-span[0])
        i = span[0]+1
        match = pat.search(s,i)
    return ''.join(sout)

txt = 'bananaappleorangestrawberryapplepear'
pats = ('apple', 'plepe', 'leoran', 'lemon')
print do_xs(txt,pats)

基本上,我创建了一个正则表达式模式,可以匹配任何输入的模式。然后我只需在最近一次匹配的起始位置后面开始重新搜索。不过,如果你输入的某个模式是另一个模式的前缀,可能会出现问题。

1
>>> string_ = 'bananaappleorangestrawberryapplepear'
>>> words = ('apple', 'plepe', 'leoran', 'lemon')
>>> xes = [(string_.find(w), len(w)) for w in words]
>>> xes
[(6, 5), (29, 5), (9, 6), (-1, 5)]
>>> for index, len_ in xes:
...   if index == -1: continue
...   string_ = string_.replace(string_[index:index+len_], 'x'*len_)
...
>>> string_
'bananaxxxxxxxxxgestrawberryxxxxxxxar'
>>>

肯定有更有效的方法,但过早的优化才是万恶之源。

3
import re

words = ('apple', 'plepe', 'leoran', 'lemon')
s = 'bananaappleorangestrawberryapplepear'

x = set()

for w in words:
    for m in re.finditer(w, s):
        i = m.start()
        for j in range(i, i+len(w)):
            x.add(j)

result = ''.join(('x' if i in x else s[i]) for i in range(len(s)))
print result

产生:

bananaxxxxxxxxxgestrawberryxxxxxxxar

撰写回答