我想使用.replace函数替换多个字符串。
我目前有
string.replace("condition1", "")
但想要一些像
string.replace("condition1", "").replace("condition2", "text")
尽管这样的语法感觉不太好
正确的做法是什么?有点像在grep/regex中,你可以用\1和\2来替换某些搜索字符串的字段
我想使用.replace函数替换多个字符串。
我目前有
string.replace("condition1", "")
但想要一些像
string.replace("condition1", "").replace("condition2", "text")
尽管这样的语法感觉不太好
正确的做法是什么?有点像在grep/regex中,你可以用\1和\2来替换某些搜索字符串的字段
当前回答
我不知道速度如何,但这是我日常的快速解决方法:
reduce(lambda a, b: a.replace(*b)
, [('o','W'), ('t','X')] #iterable of pairs: (oldval, newval)
, 'tomato' #The string from which to replace values
)
... 但我喜欢上面的#1正则表达式答案。注意:如果一个新值是另一个值的子字符串,那么该操作是不可交换的。
其他回答
您可以使用pandas库和replace函数,它既支持精确匹配,也支持正则表达式替换。例如:
df = pd.DataFrame({'text': ['Billy is going to visit Rome in November', 'I was born in 10/10/2010', 'I will be there at 20:00']})
to_replace=['Billy','Rome','January|February|March|April|May|June|July|August|September|October|November|December', '\d{2}:\d{2}', '\d{2}/\d{2}/\d{4}']
replace_with=['name','city','month','time', 'date']
print(df.text.replace(to_replace, replace_with, regex=True))
修改后的文本为:
0 name is going to visit city in month
1 I was born in date
2 I will be there at time
你可以在这里找到一个例子。请注意,文本上的替换是按照它们在列表中出现的顺序进行的
你可以做一个漂亮的循环函数。
def replace_all(text, dic):
for i, j in dic.iteritems():
text = text.replace(i, j)
return text
其中text是完整的字符串,dic是字典-每个定义都是一个字符串,将替换与术语匹配的字符串。
注意:在Python 3中,iteritems()已被items()取代
注意:Python字典没有迭代的可靠顺序。此解决方案仅在以下情况下解决您的问题:
替换的顺序无关紧要 替换者可以改变之前替换者的结果
更新:上述与插入顺序相关的语句不适用于大于或等于3.6的Python版本,因为标准字典已更改为使用插入顺序进行迭代。
例如:
d = { "cat": "dog", "dog": "pig"}
my_sentence = "This is my cat and this is my dog."
replace_all(my_sentence, d)
print(my_sentence)
可能输出#1:
"This is my pig and this is my pig."
可能的输出#2
"This is my dog and this is my pig."
一个可能的解决方法是使用OrderedDict。
from collections import OrderedDict
def replace_all(text, dic):
for i, j in dic.items():
text = text.replace(i, j)
return text
od = OrderedDict([("cat", "dog"), ("dog", "pig")])
my_sentence = "This is my cat and this is my dog."
replace_all(my_sentence, od)
print(my_sentence)
输出:
"This is my pig and this is my pig."
注意事项#2:如果你的文本字符串太大或字典中有很多对,效率就会很低。
这里有一个使用reduce的第一个解决方案的变体,如果你喜欢功能性的。:)
repls = {'hello' : 'goodbye', 'world' : 'earth'}
s = 'hello, world'
reduce(lambda a, kv: a.replace(*kv), repls.iteritems(), s)
马蒂诺的版本更好:
repls = ('hello', 'goodbye'), ('world', 'earth')
s = 'hello, world'
reduce(lambda a, kv: a.replace(*kv), repls, s)
注意:测试你的案例,见注释。
这里有一个例子,它在长弦上更有效,有许多小的替换。
source = "Here is foo, it does moo!"
replacements = {
'is': 'was', # replace 'is' with 'was'
'does': 'did',
'!': '?'
}
def replace(source, replacements):
finder = re.compile("|".join(re.escape(k) for k in replacements.keys())) # matches every string we want replaced
result = []
pos = 0
while True:
match = finder.search(source, pos)
if match:
# cut off the part up until match
result.append(source[pos : match.start()])
# cut off the matched part and replace it in place
result.append(replacements[source[match.start() : match.end()]])
pos = match.end()
else:
# the rest after the last match
result.append(source[pos:])
break
return "".join(result)
print replace(source, replacements)
关键是要避免长字符串的多次连接。我们将源字符串切成片段,在我们形成列表时替换一些片段,然后将整个字符串连接回字符串。
我不知道速度如何,但这是我日常的快速解决方法:
reduce(lambda a, b: a.replace(*b)
, [('o','W'), ('t','X')] #iterable of pairs: (oldval, newval)
, 'tomato' #The string from which to replace values
)
... 但我喜欢上面的#1正则表达式答案。注意:如果一个新值是另一个值的子字符串,那么该操作是不可交换的。