【发布时间】:2019-12-12 21:37:27
【问题描述】:
我有一个字符串s、一个模式p 和一个替换r,我需要获取字符串列表,其中只有一个与p 匹配已被替换为r。
例子:
s = 'AbcAbAcc'
p = 'A'
r = '_'
// Output:
['_bcAbAcc', 'Abc_bAcc', 'AbcAb_cc']
我尝试过使用re.finditer(p, s),但我不知道如何用r 替换每个匹配项。
【问题讨论】:
我有一个字符串s、一个模式p 和一个替换r,我需要获取字符串列表,其中只有一个与p 匹配已被替换为r。
例子:
s = 'AbcAbAcc'
p = 'A'
r = '_'
// Output:
['_bcAbAcc', 'Abc_bAcc', 'AbcAb_cc']
我尝试过使用re.finditer(p, s),但我不知道如何用r 替换每个匹配项。
【问题讨论】:
您可以在找到所有匹配项后手动替换它们:
[s[:m.start()] + r + s[m.end():] for m in re.finditer(p,s)]
结果是:
['_bcAbAcc', 'Abc_bAcc', 'AbcAb_cc']
它是如何工作的?
re.finditer(p,s) 将找到所有匹配项(每个匹配项都是 re.Match
对象)re.Match 对象具有返回匹配位置的 start() 和 end() 方法s[:begin] + replacement + s[end:]
【讨论】:
m.start() 代替m.span()[0] 和m.end() 代替m.span()[1]。
你不需要正则表达式,它很简单
[s[:i]+r+s[i+1:] for i,c in enumerate(s) if c==p]
完整代码:See it working here
s = 'AbcAbAcc'
p = 'A'
r = '_'
x = [s[:i]+r+s[i+1:] for i,c in enumerate(s) if c==p]
print(x)
输出:
['_bcAbAcc', 'Abc_bAcc', 'AbcAb_cc']
如前所述,这仅适用于一个字符,对于超过一个字符或需要正则表达式的任何内容,请使用 zvone's answer。
对于我的答案和 zvone 的答案之间的性能比较(以及不使用正则表达式的第三种方法),请参阅 here 或使用以下代码自行测试:
import timeit,re
s = 'AbcAbAcc'
p = 'A'
r = '_'
def x1():
return [s[:i]+r+s[i+1:] for i,c in enumerate(s) if c==p]
def x2():
return [s[:i]+r+s[i+1:] for i in range(len(s)) if s[i]==p]
def x3():
return [s[:m.start()] + r + s[m.end():] for m in re.finditer(p,s)]
print(x1())
print(timeit.timeit(x1, number=100000))
print(x2())
print(timeit.timeit(x2, number=100000))
print(x3())
print(timeit.timeit(x3, number=100000))
【讨论】:
p 总是一个字符长时才这样,但我需要p 将是一个实际的模式。但是,我提供的示例可以完美运行!