90

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)例外をスローします:

ソース配列の少なくとも 1 つの要素が、宛先配列型にキャストできませんでした。

4

6 に答える 6

185

試す:

var arr = Regex.Matches(strText, @"\b[A-Za-z-']+\b")
    .Cast<Match>()
    .Select(m => m.Value)
    .ToArray();
于 2012-07-10T15:02:42.170 に答える
33

Dave Bish の答えは適切で、適切に機能します。

Cast<Match>()に置き換えるとOfType<Match>()速度が向上しますが、注目に値します。

コードは次のようになります。

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() は遅くなります。

于 2012-07-10T15:28:18.980 に答える
6

Alex が投稿したものとまったく同じベンチマークを実行したところ、より速い場合もあればCastより速い場合もありましOfTypeたが、両者の違いはごくわずかでした。ただし、醜いものの、for ループは他の 2 つのループより一貫して高速です。

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
于 2014-05-14T13:55:45.497 に答える
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();
于 2013-11-22T02:01:04.227 に答える