Python 用符号序列替换字符串中的关键字
作为练习,我必须创建一个简单的亵渎过滤器来了解类 过滤器使用一系列令人反感的关键字和替换模板进行初始化。这些单词的每一次出现都应替换为模板生成的字符串。如果单词大小比模板短,则应使用从头到尾的子字符串。如果单词大小较长,则应根据需要重复模板 下面是我迄今为止的结果,并举了一个例子Python 用符号序列替换字符串中的关键字,python,string,class,replace,Python,String,Class,Replace,作为练习,我必须创建一个简单的亵渎过滤器来了解类 过滤器使用一系列令人反感的关键字和替换模板进行初始化。这些单词的每一次出现都应替换为模板生成的字符串。如果单词大小比模板短,则应使用从头到尾的子字符串。如果单词大小较长,则应根据需要重复模板 下面是我迄今为止的结果,并举了一个例子 class ProfanityFilter: def __init__(self, keywords, template): self.__keywords = sorted(keywords
class ProfanityFilter:
def __init__(self, keywords, template):
self.__keywords = sorted(keywords, key=len, reverse=True)
self.__template = template
def filter(self, msg):
def __replace_letters__(old_word, replace_str):
replaced_word = ""
old_index = 0
replace_index = 0
while old_index <= len(old_word):
if replace_index == len(replace_str):
replace_index = 0
else:
replaced_word += replace_str[replace_index]
replace_index += 1
old_index += 1
return replaced_word
for keyword in self.__keywords:
idx = 0
while idx < len(msg):
index_l = msg.lower().find(keyword.lower(), idx)
if index_l == -1:
break
msg = msg[:index_l] + __replace_letters__(keyword, self.__template) + msg[index_l + len(keyword):]
idx = index_l + len(keyword)
return msg
f = ProfanityFilter(["duck", "shot", "batch", "mastard"], "?#$")
offensive_msg = "this mastard shot my duck"
clean_msg = f.filter(offensive_msg)
print(clean_msg) # should be: "this ?#$?#$? ?#$? my ?#$?"
但它显示:
this ?#$?#$ ?#$? my ?#$?
出于某种原因,它将“mastard”一词替换为6个符号,而不是7个(每个字母一个)。它适用于其他关键字,为什么不适用于这个
另外,如果你看到任何其他不对劲的事情,请随时告诉我。请记住,我是初学者,我的“工具箱”非常小。我会用正则表达式来代替,因为
re.sub()
有一个方便的API用于动态替换:
重新导入
类别亵渎过滤器:
定义初始化(自我、关键字、模板):
#构建一个正则表达式,它将匹配所有亵渎的单词
self.keyword_re=re.compile(“|”)
self.template=模板
def_生成_替换(自身、word):
l=len(字)
#计算重复模板的次数
重复=(l//len(self.template))+1
#因为我们可能会得到一个比原来长的字符串,
#切成正确的长度。
返回(self.template*重复)[:l]
def过滤器(自身,msg):
#将正则表达式的所有匹配项替换为
#动态计算的替换值。
返回self.keyword\u re.sub(
lambda m:self.\u生成\u替换(m.group(0)),
味精,
)
f=亵渎过滤器([“鸭子”、“射击”、“批次”、“马斯塔德”]、“?#$”)
进攻性的\u msg=“这只母鸭射中了我的鸭子”
打印(f.过滤器(攻击性信息))
您的问题在于索引逻辑。你有两个错误
while old_index <= len(old_word):
if replace_index == len(replace_str):
replace_index = 0
# You don't replace a letter; you just reset the new index, but ...
else:
replaced_word += replace_str[replace_index]
replace_index += 1
old_index += 1 # ... but you still advance the old index.
输出:
?#$?#$?#$?# on ?#$ rulez!
输入字为13和2个字母;替换的是11和3
修复这两个错误:使old_index
保持在范围内,并仅在进行替换时增加它
while old_index < len(old_word):
if replace_index == len(replace_str):
replace_index = 0
else:
replaced_word += replace_str[replace_index]
replace_index += 1
old_index += 1
旧索引
未来的改进:
- 将其重构为
循环for
- 不要重置替换索引;事实上,摆脱它。只需使用
旧索引%len(替换str)
- 无法生成一行程序,但这里有一个糟糕的实现。不要做VoNWooDSoN做的事:
编辑
所以,我猜3.8有赋值表达式。。。所以,但这将是一个班轮那么(可能)
?#$?#$?#$?# on ?#$ rulez!
while old_index < len(old_word):
if replace_index == len(replace_str):
replace_index = 0
else:
replaced_word += replace_str[replace_index]
replace_index += 1
old_index += 1
def replace(msg, keywords=["duck", "shot", "batch", "mastard"], template="?#$"):
for keyword in keywords * len(msg)):
msg = (template*len(keyword))[:len(keyword)].join([msg[:msg.find(keyword)], msg[msg.find(keyword)+len(keyword):]]) if msg.find(keyword) > 0 else msg
return msg
offensive_msg = "this mastard shot my duck"
clean_msg = replace(offensive_msg)
print(clean_msg) # should be: "this ?#$?#$? ?#$? my ?#$?"
print(clean_msg=="this ?#$?#$? ?#$? my ?#$?")
print ((lambda msg: [msg := (("?#$"*len(keyword))[:len(keyword)].join([msg[:msg.find(keyword)], msg[msg.find(keyword)+len(keyword):]]) if msg.find(keyword) > 0 else msg) for keyword in ["duck", "shot", "batch", "mastard"]])("this mastard shot my duck")[-1])