【发布时间】:2018-08-22 16:49:30
【问题描述】:
给定一个字符串和一个应替换为占位符的子字符串列表,例如
import re
from copy import copy
phrases = ["'s morgen", "'s-Hertogenbosch", "depository financial institution"]
original_text = "Something, 's morgen, ik 's-Hertogenbosch im das depository financial institution gehen"
第一个目标是首先将original_text 中phrases 中的子字符串替换为索引占位符,例如
text = copy(original_text)
backplacement = {}
for i, phrase in enumerate(phrases):
backplacement["MWEPHRASE{}".format(i)] = phrase.replace(' ', '_')
text = re.sub(r"{}".format(phrase), "MWEPHRASE{}".format(i), text)
print(text)
[出]:
Something, MWEPHRASE0, ik MWEPHRASE1 im das MWEPHRASE2 gehen
然后会有一些函数来使用占位符来操作text,例如
cleaned_text = func('Something, MWEPHRASE0, ik MWEPHRASE1 im das MWEPHRASE2 gehen')
print(cleaned_text)
输出:
MWEPHRASE0 ik MWEPHRASE1 MWEPHRASE2
最后一步是我们以向后的方式进行替换并放回原来的短语,即
' '.join([backplacement[tok] if tok in backplacement else tok for tok in clean_text.split()])
[出]:
"'s_morgen ik 's-Hertogenbosch depository_financial_institution"
问题是:
- 如果
phrases中的子字符串列表很大,那么第一次替换和最后一次替换的时间会很长。
有没有办法用正则表达式进行替换/替换?
- 使用
re.sub(r"{}".format(phrase), "MWEPHRASE{}".format(i), text)正则表达式替换不是很有帮助,尤其是。如果短语中存在与完整单词不匹配的子字符串,
例如
phrases = ["org", "'s-Hertogenbosch", "depository financial institution"]
original_text = "Something, 's morgen, ik 's-Hertogenbosch im das depository financial institution gehen"
backplacement = {}
text = copy(original_text)
for i, phrase in enumerate(phrases):
backplacement["MWEPHRASE{}".format(i)] = phrase.replace(' ', '_')
text = re.sub(r"{}".format(phrase), "MWEPHRASE{}".format(i), text)
print(text)
我们得到一个尴尬的输出:
Something, 's mMWEPHRASE0en, ik MWEPHRASE1 im das MWEPHRASE2 gehen
我尝试过使用'\b{}\b'.format(phrase),但这不适用于带有标点符号的短语,即
phrases = ["'s morgen", "'s-Hertogenbosch", "depository financial institution"]
original_text = "Something, 's morgen, ik 's-Hertogenbosch im das depository financial institution gehen"
backplacement = {}
text = copy(original_text)
for i, phrase in enumerate(phrases):
backplacement["MWEPHRASE{}".format(i)] = phrase.replace(' ', '_')
text = re.sub(r"\b{}\b".format(phrase), "MWEPHRASE{}".format(i), text)
print(text)
[出]:
Something, 's morgen, ik 's-Hertogenbosch im das MWEPHRASE2 gehen
re.sub 正则表达式模式中的短语是否有一些地方可以表示词的边界?
【问题讨论】:
-
在您想要的输出中,除了
ik之外,所有未出现在phrases中的字符串都将被删除。这是为什么呢? -
你这样做很困难。
Then there'll be some functions to manipulate the text with the placeholders。因此,您可以在添加占位符后处理文本。并且该函数必须对空格或其他内容进行拆分。所以,现在您有一个数组,您可以在其中操作除占位符之外的所有元素,然后您想将数组连接成一个字符串,然后使用真实单词替换占位符。对吗? -
单次通过,我会使用正则表达式匹配所有单词并将它们放入二维数组(或列表)中。维度 0 是字符串部分,维度 1 是标志。当匹配非短语字符串部分时,标志为 0,当它是短语词时,标志为 1。然后您可以迭代数组并忽略标志为 1 的部分。添加、删除、重新排列根据需要的元素。然后将它们重新组合在一起。正则表达式很简单
((?:(?!phrase1|phrase2|phrase3)[\S\s])+)|(phrase1|phrase2|phrase3)。其中,捕获组 1 是非短语字符串部分,捕获组 2 是短语。 -
这似乎是另一种选择:github.com/vi3k6i5/flashtext
-
至于单词边界,你一定要找
r"(?<!\w){}(?!\w)".format(phrase)。由于您的某些关键字以非单词字符开头,因此您不能使用\b。您能否提供更多需要实现的逻辑?看起来您可能需要将回调/lambda 作为第二个参数传递给re.sub以将每个匹配项替换一次。
标签: python regex string replace placeholder