从字符串列表中删除子字符串

时间:2012-04-07 20:24:45

标签: c# regex linq list replace

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

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

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

4 个答案:

答案 0 :(得分:2)

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

如果你想查找像more than one word这样的子句,你就不能再在空格上分割了。你必须回到String.IndexOf()

答案 1 :(得分:2)

简单的String.Replace无效,因为它会删除单词部分。如果“性别”是一个被禁止的单词并且你有“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)");

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

您可以使用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, "");

答案 2 :(得分:1)

如果你正在追求它的表现,我认为你并不担心一次性设置时间,而是担心持续性能。因此,我将构建一个包含所有禁用表达式的大型正则表达式,并确保它已编译 - 这是一个设置。

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

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

答案 3 :(得分: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>