Dot-Net

將 IEnumerable<char> 轉換為字元串的最佳方法?

  • November 12, 2011

為什麼不能使用流利的語言string

例如:

var x = "asdf1234";
var y = new string(x.TakeWhile(char.IsLetter).ToArray());

難道沒有更好的轉換IEnumerable&lt;char&gt;方式string嗎?

這是我做的一個測試:

class Program
{
 static string input = "asdf1234";
 static void Main()
 {
   Console.WriteLine("1000 times:");
   RunTest(1000, input);
   Console.WriteLine("10000 times:");
   RunTest(10000,input);
   Console.WriteLine("100000 times:");
   RunTest(100000, input);
   Console.WriteLine("100000 times:");
   RunTest(100000, "ffff57467");


   Console.ReadKey();

 }

 static void RunTest( int times, string input)
 {

   Stopwatch sw = new Stopwatch();

   sw.Start();
   for (int i = 0; i &lt; times; i++)
   {
     string output = new string(input.TakeWhile(char.IsLetter).ToArray());
   }
   sw.Stop();
   var first = sw.ElapsedTicks;

   sw.Restart();
   for (int i = 0; i &lt; times; i++)
   {
     string output = Regex.Match(input, @"^[A-Z]+", 
       RegexOptions.IgnoreCase).Value;
   }
   sw.Stop();
   var second = sw.ElapsedTicks;

   var regex = new Regex(@"^[A-Z]+", 
     RegexOptions.IgnoreCase);
   sw.Restart();
   for (int i = 0; i &lt; times; i++)
   {
     var output = regex.Match(input).Value;
   }
   sw.Stop();
   var third = sw.ElapsedTicks;

   double percent = (first + second + third) / 100;
   double p1 = ( first / percent)/  100;
   double p2 = (second / percent )/100;
   double p3 = (third / percent  )/100;


   Console.WriteLine("TakeWhile took {0} ({1:P2}).,", first, p1);
   Console.WriteLine("Regex took {0}, ({1:P2})." , second,p2);
   Console.WriteLine("Preinstantiated Regex took {0}, ({1:P2}).", third,p3);
   Console.WriteLine();
 }
}

結果:

1000 times:
TakeWhile took 11217 (62.32%).,
Regex took 5044, (28.02%).
Preinstantiated Regex took 1741, (9.67%).

10000 times:
TakeWhile took 9210 (14.78%).,
Regex took 32461, (52.10%).
Preinstantiated Regex took 20669, (33.18%).

100000 times:
TakeWhile took 74945 (13.10%).,
Regex took 324520, (56.70%).
Preinstantiated Regex took 172913, (30.21%).

100000 times:
TakeWhile took 74511 (13.77%).,
Regex took 297760, (55.03%).
Preinstantiated Regex took 168911, (31.22%).

結論:我懷疑什麼是更好的選擇,我想我會繼續,TakeWhile只有在第一次執行時最慢。

無論如何,我的問題是是否有任何方法可以通過重新排列函式的結果來優化性能TakeWhile

假設您主要尋找性能,那麼這樣的事情應該比您的任何範例都快得多:

string x = "asdf1234";
string y = x.LeadingLettersOnly();

// ...

public static class StringExtensions
{
   public static string LeadingLettersOnly(this string source)
   {
       if (source == null)
           throw new ArgumentNullException("source");

       if (source.Length == 0)
           return source;

       char[] buffer = new char[source.Length];
       int bufferIndex = 0;

       for (int sourceIndex = 0; sourceIndex &lt; source.Length; sourceIndex++)
       {
           char c = source[sourceIndex];

           if (!char.IsLetter(c))
               break;

           buffer[bufferIndex++] = c;
       }
       return new string(buffer, 0, bufferIndex);
   }
}

如何將其轉換IEnumerable&lt;char&gt;string

string.Concat(x.TakeWhile(char.IsLetter));

引用自:https://stackoverflow.com/questions/8108313