在C#中使用正则表达式,有没有办法在包含各种单词和符号的字符串中查找和删除重复的单词或符号?
前。
首字母词组:
“我喜欢环境。环境很好。”
所需字符串:
“我喜欢环境。很好”
删除了重复项:“the”,“environment”,“。”
答案 0 :(得分:13)
正如其他人所说,你需要的不仅仅是一个正则表达式来跟踪单词:
var words = new HashSet<string>();
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);
答案 1 :(得分:11)
这似乎对我有用
(\b\S+\b)(?=.*\1)
匹配如此
apple apple orange orange red blue green orange green blue pirates ninjas cowboys ninjas pirates
答案 2 :(得分:4)
好吧,杰夫告诉我如何使用表达式反向引用的魔力和全局修饰符来实现这一点,所以我原来的答案是不可行的。你们都应该投票支持杰夫的回答。但是,对于后代,我会注意到这个中有一个棘手的小正则表达式引擎敏感度问题,如果你使用的是Perl风格的正则表达式,你需要这样做:
\b(\S+)\b(?=.*\b\1\b.*)
而不是杰夫的答案,因为C#的正则表达式将有效捕获\b
中的\1
,但PCRE不会。{/ p>
答案 3 :(得分:2)
看看后面的参考:
http://msdn.microsoft.com/en-us/library/thwdfzxy(VS.71).aspx
这是一个会发现双字的正则表达式。但它每匹配只匹配一个单词。所以你不得不多次使用它。
new Regex( @"(.*)\b(\w+)\b(.*)(\2)(.*)", RegexOptions.IgnoreCase );
当然这不是最好的解决方案(参见其他答案,建议不要使用正则表达式)。但是你要求一个正则表达式 - 这是一个。也许只是这个想法可以帮助你...
答案 4 :(得分:1)
正则表达式是解决此问题的“工具”的不良选择。也许以下方法可行:
HashSet<string> corpus = new HashSet<string>();
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
编辑:这是我做出一个很大的假设,即你正在为搜索等某种分析而“兴奋”。
答案 5 :(得分:0)
正则表达不适合一切。像你的问题确实属于那个类别。我建议你改用解析器。
答案 6 :(得分:0)
请参阅When not to use Regex in C# (or Java, C++ etc)
当然使用正则表达式将字符串拆分为单词可能是一个有用的第一步,但是String.Split()是清晰的,并且很难完成所需的一切。
答案 7 :(得分:-1)
您将无法使用正则表达式来解决此问题,因为正则表达式只匹配常规语言。您尝试匹配的模式是上下文相关的,因此不是“常规”。
幸运的是,编写解析器很容易。看看Per Erik Stendahl的代码。
答案 8 :(得分:-2)
正如其他人所指出的,这可以通过反向引用来实现。有关如何在.Net中使用反向引用的详细信息,请参阅 http://msdn.microsoft.com/nb-no/library/thwdfzxy(en-us).aspx。
删除标点符号的特定问题也使它更复杂,但我认为沿着这些行的代码(空格在该正则表达式中并不重要)应该可以解决这个问题:
(\b\w+(?:\s+\w+)*)\s+\1
我根本没有测试过正则表达式,但这应该匹配由重复的空格分隔的一个或多个单词。你将不得不添加一些逻辑来允许惩罚等等。