0

我有一个包含禁用词的字符串列表。检查字符串是否包含任何被禁止的单词并将其从字符串中删除的有效方法是什么?目前,我有这个:

cleaned = String.Join(" ", str.Split().Where(b => !bannedWords.Contains(b,
                            StringComparer.OrdinalIgnoreCase)).ToArray());

这适用于单个禁用词,但不适用于短语(例如more than one word)。的任何实例more than one word也应该被删除。我想尝试的另一种方法是使用 List 的 Contains 方法,但它只返回一个布尔值,而不是匹配词的索引。如果我可以获得匹配词的索引,我可以使用String.Replace(bannedWords[i],"");

4

4 回答 4

2

它不起作用,因为您有冲突的定义。

当您想查找more than one word无法再拆分空格的子句时。你将不得不依靠String.IndexOf()

于 2012-04-07T20:29:33.230 回答
2

一个简单的String.Replace将不起作用,因为它会删除单词部分。如果“sex”是一个被禁止的词,而你有“sextet”这个词,它没有被禁止,你应该保持原样。

使用Regex您可以在文本中找到整个单词和短语

string text = "A sextet is a musical composition for six instruments or voices.".
string word = "sex";
var matches = Regex.Matches(text, @"(?<=\b)" + word + @"(?=\b)");

在这种情况下,matches 集合将为空。

您可以使用该Regex.Replace方法

foreach (string word in bannedWords) {
    text = Regex.Replace(text, @"(?<=\b)" + word + @"(?=\b)", "")
}

注意:我使用了以下Regex模式

(?<=prefix)find(?=suffix)

其中 'prefix' 和 'suffix' 都是\b,表示单词的开头和结尾。

如果您的禁止字词或短语可以包含特殊字符,则使用 . 转义它们会更安全Regex.Escape(word)


使用@zmbq 的想法,您可以创建一个Regex模式一次

string pattern =
    @"(?<=\b)(" +
    String.Join(
        "|",
        bannedWords
            .Select(w => Regex.Escape(w))
            .ToArray()) +
     @")(?=\b)";
var regex = new Regex(pattern); // Is compiled by default

然后将其重复应用于不同的文本

string result = regex.Replace(text, "");
于 2012-04-07T20:46:16.840 回答
1

如果您追求的是性能,我假设您不担心一次性设置时间,而是担心持续性能。所以我会构建一个包含所有被禁止的表达式的巨大正则表达式,并确保它被编译——这是一个设置。

然后我会尝试将它与文本进行匹配,并将每个匹配项替换为空白或您想要替换的任何内容。

这样做的原因是,一个大的正则表达式应该编译成类似于你手动创建的有限状态自动机来处理这个问题的东西,所以它应该运行得很好。

于 2012-04-07T20:32:04.710 回答
0

你为什么不遍历禁用词列表并使用 方法在字符串中查找它们中的每一个string.IndexOf。例如,您可以使用以下代码删除被禁止的单词和短语:

myForbWords.ForEach(delegate(string item) {
    int occ = str.IndexOf(item);
    if(occ > -1) str = str.Remove(occ, item.Length);
});

myForbWords 的类型是List<string>.

于 2012-04-07T20:49:21.740 回答