将MatchCollection转换为字符串数组

有没有比这更好的方法将MatchCollection转换为字符串数组?

MatchCollection mc = Regex.Matches(strText, @"\b[A-Za-z-']+\b"); string[] strArray = new string[mc.Count]; for (int i = 0; i < mc.Count;i++ ) { strArray[i] = mc[i].Groups[0].Value; } 

PS: mc.CopyTo(strArray,0)抛出exception:

源数组中至少有一个元素无法转换为目标数组类型。

尝试:

 var arr = Regex.Matches(strText, @"\b[A-Za-z-']+\b") .Cast() .Select(m => m.Value) .ToArray(); 

Dave Bish的答案很好并且运作正常。

值得注意的是,尽管用OfType()替换Cast() OfType()会加快速度。

代码成为:

 var arr = Regex.Matches(strText, @"\b[A-Za-z-']+\b") .OfType() .Select(m => m.Groups[0].Value) .ToArray(); 

结果完全相同(并以完全相同的方式解决OP的问题),但对于大字符串,它更快。

测试代码:

 // put it in a console application static void Test() { Stopwatch sw = new Stopwatch(); StringBuilder sb = new StringBuilder(); string strText = "this will become a very long string after my code has done appending it to the stringbuilder "; Enumerable.Range(1, 100000).ToList().ForEach(i => sb.Append(strText)); strText = sb.ToString(); sw.Start(); var arr = Regex.Matches(strText, @"\b[A-Za-z-']+\b") .OfType() .Select(m => m.Groups[0].Value) .ToArray(); sw.Stop(); Console.WriteLine("OfType: " + sw.ElapsedMilliseconds.ToString()); sw.Reset(); sw.Start(); var arr2 = Regex.Matches(strText, @"\b[A-Za-z-']+\b") .Cast() .Select(m => m.Groups[0].Value) .ToArray(); sw.Stop(); Console.WriteLine("Cast: " + sw.ElapsedMilliseconds.ToString()); } 

输出如下:

 OfType: 6540 Cast: 8743 

对于很长的字符串,Cast()因此更慢。

我运行了Alex发布的完全相同的基准测试,发现有时Cast更快,有时OfType更快,但两者之间的差异可以忽略不计。 然而,虽然丑陋,但for循环始终比其他两个都快。

 Stopwatch sw = new Stopwatch(); StringBuilder sb = new StringBuilder(); string strText = "this will become a very long string after my code has done appending it to the stringbuilder "; Enumerable.Range(1, 100000).ToList().ForEach(i => sb.Append(strText)); strText = sb.ToString(); //First two benchmarks sw.Start(); MatchCollection mc = Regex.Matches(strText, @"\b[A-Za-z-']+\b"); var matches = new string[mc.Count]; for (int i = 0; i < matches.Length; i++) { matches[i] = mc[i].ToString(); } sw.Stop(); 

结果:

 OfType: 3462 Cast: 3499 For: 2650 

也可以使用这种扩展方法来处理MatchCollection不是通用的烦恼。 并不是说这是一个大问题,但这几乎肯定比OfTypeCastOfType ,因为它只是枚举,这两者都必须这样做。

(旁注:我想知道.NET团队是否有可能在将来使MatchCollectioninheritanceICollectionIEnumerable通用版本?那么我们就不需要这个额外的步骤来立即提供LINQ转换)

  public static IEnumerable ToEnumerable(this MatchCollection mc) { if (mc != null) { foreach (Match m in mc) yield return m; } } 

考虑以下代码……

 var emailAddress = "joe@sad.com; joe@happy.com; joe@elated.com"; List emails = new List(); emails = Regex.Matches(emailAddress, @"([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})") .Cast() .Select(m => m.Groups[0].Value) .ToList(); 

祝好运!