用于查找和删除重复单词的正则表达式

在C#中使用正则表达式,有没有办法在包含各种单词和符号的字符串中查找和删除重复的单词或符号?

防爆。

初始字符串:

“我喜欢环境。环境很好。”

所需的字符串:

“我喜欢环境。很好”

删除了重复项: “the”,“environment”,“。”

正如其他人所说,你需要的不仅仅是正则表达式来跟踪单词:

var words = new HashSet(); string text = "I like the environment. The environment is good."; text = Regex.Replace(text, "\\w+", m => words.Add(m.Value.ToUpperInvariant()) ? m.Value : String.Empty); 

这似乎对我有用

 (\b\S+\b)(?=.*\1) 

匹配就好

 苹果苹果橙  
 橙色红色蓝色 绿色橙色绿色蓝色  
 海盗 忍者牛仔忍者海盗  

好吧,杰夫已经向我展示了如何使用表达式反向引用的魔力和全局修饰符来实现这一点,所以我原来的答案是不可行的。 你们都应该投票支持杰夫的回答。 但是,对于后人,我会注意到这个中有一个棘手的小正则表达式引擎敏感度问题,如果你使用的是Perl风格的正则表达式,你需要这样做:

 \b(\S+)\b(?=.*\b\1\b.*) 

而不是杰夫的答案,因为C#的正则表达式将有效地捕获\1 in \1但PCRE不会。

看看后面的参考:
http://msdn.microsoft.com/en-us/library/thwdfzxy(VS.71).aspx

这是一个会发现双字的正则表达式。 但它每匹配只匹配一个单词。 所以你不得不多次使用它。

 new Regex( @"(.*)\b(\w+)\b(.*)(\2)(.*)", RegexOptions.IgnoreCase ); 

当然,这不是最好的解决方案(参见其他答案,建议不要使用正则表达式)。 但是你要求一个正则表达式 – 这是一个。 也许只是这个想法可以帮助你……

正则表达式是解决这个问题的“工具”的不良选择。 也许以下可能有效:

 HashSet corpus = new HashSet(); char[] split = new char[] { ' ', '\t', '\r', '\n', '.', ';', ',', ':', ... }; foreach (string line in inputLines) { string[] parts = line.Split(split, StringSplitOptions.RemoveEmptyEntries); foreach (string part in parts) { corpus.Add(part.ToUpperInvariant()); } } // 'corpus' now contains all of the unique tokens 

编辑:这是我做出一个很大的假设,你正在为搜索等某种分析“兴奋”。

正则表达式不适合一切。 像你的问题一样属于那个类别。 我建议你改用解析器。

有些人在遇到问题时会想“我知道,我会使用正则表达式。”现在他们有两个问题。

请参阅何时不在C#中使用Regex(或Java,C ++等)

当然使用正则表达式将字符串拆分为单词可能是一个有用的第一步,但是String.Split()是清晰的,它可以完成所需的一切。

您将无法使用正则表达式来解决此问题,因为正则表达式只匹配常规语言。 您尝试匹配的模式是上下文相关的,因此不是“常规”。

幸运的是,编写解析器很容易。 看看Per Erik Stendahl的代码。

正如其他人所指出的那样,这可以通过反向引用来实现。 有关如何在.Net中使用反向引用的详细信息,请参见http://msdn.microsoft.com/nb-no/library/thwdfzxy(en-us).aspx 。

删除标点符号的特定问题也使它更复杂,但我认为沿着这些行的代码(空格在该正则表达式中并不重要)应该可以解决问题:

 (\b\w+(?:\s+\w+)*)\s+\1 

我根本没有测试过正则表达式,但是它应该匹配由重复的空格分隔的一个或多个单词。 你将不得不添加一些逻辑来允许惩罚等等。