有没有比这更好的方法将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;
}
P.S。:mc.CopyTo(strArray,0)
抛出异常:
源数组中至少有一个元素无法转换为目标数组类型。
答案 0 :(得分:137)
尝试:
var arr = Regex.Matches(strText, @"\b[A-Za-z-']+\b")
.Cast<Match>()
.Select(m => m.Value)
.ToArray();
答案 1 :(得分:26)
Dave Bish的回答很好并且运作正常。
值得注意的是,将Cast<Match>()
替换为OfType<Match>()
会加快速度。
Code wold成为:
var arr = Regex.Matches(strText, @"\b[A-Za-z-']+\b")
.OfType<Match>()
.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<Match>()
.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<Match>()
.Select(m => m.Groups[0].Value)
.ToArray();
sw.Stop();
Console.WriteLine("Cast: " + sw.ElapsedMilliseconds.ToString());
}
输出如下:
OfType: 6540
Cast: 8743
对于很长的字符串,Cast()因此更慢。
答案 2 :(得分:5)
我运行了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
答案 3 :(得分:1)
也可以使用这种扩展方法来处理MatchCollection
不通用的烦恼。并不是说这是一个大问题,但这几乎肯定比OfType
或Cast
更高效,因为它只是枚举,这两者都必须这样做。
(旁注:我想知道.NET团队是否有可能在将来MatchCollection
继承ICollection
和IEnumerable
的通用版本?然后我们就不会这样做了; t需要这个额外的步骤才能立即获得LINQ转换。
public static IEnumerable<Match> ToEnumerable(this MatchCollection mc)
{
if (mc != null) {
foreach (Match m in mc)
yield return m;
}
}
答案 4 :(得分:0)
考虑以下代码......
var emailAddress = "joe@sad.com; joe@happy.com; joe@elated.com";
List<string> emails = new List<string>();
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<Match>()
.Select(m => m.Groups[0].Value)
.ToList();
祝你好运!