0
string s = "abcabcabcabcabc";

var foundIndexes = new List<int>();

質問はここでの議論から来ました。私は単に疑問に思っていました

どうすればこれができますか?

for (int i = s.IndexOf('a'); i > -1; i = s.IndexOf('a', i + 1))  

      foundIndexes.Add(i); 

これよりも優れている:

for (int i = 0; i < s.Length; i++)

      if (s[i] == 'a') foundIndexes.Add(i);

編集:パフォーマンスの向上はどこから来るのですか?

4

2 に答える 2

2

私は、使用IndexOfが直接ループよりも速いことに気づきませんでした。正直なところ、どちらの場合も各キャラクターをチェックする必要があるので、どうなるかわかりません。私の最初の結果はこれでした:

Found by loop, 974 ms 
Found by IndexOf 1144 ms

編集:さらに数回実行した後、上記の結果を表示するには、リリースを実行する必要があることに気付きました(つまり、最適化を使用)。最適化を行わないと、forループは実際に遅くなります。

ベンチマークコード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace Test
{
    public class Program
    {
        public static void Main(string[] args)
        {
            const string target = "abbbdbsdbsbbdbsabdbsabaababababafhdfhffadfd";

            // Jit methods
            TimeMethod(FoundIndexesLoop, target, 1);
            TimeMethod(FoundIndexesIndexOf, target, 1);            

            Console.WriteLine("Found by loop, {0} ms", TimeMethod(FoundIndexesLoop, target, 2000000));
            Console.WriteLine("Found by IndexOf {0} ms", TimeMethod(FoundIndexesIndexOf, target, 2000000));           
        }

        private static long TimeMethod(Func<string, List<int>> method, string input, int reps)
        {
            var stopwatch = Stopwatch.StartNew();
            List<int> result = null;
            for(int i = 0; i < reps; i++)
            {
                result = method(input);
            }
            stopwatch.Stop();
            TextWriter.Null.Write(result);
            return stopwatch.ElapsedMilliseconds;
        }

        private static List<int> FoundIndexesIndexOf(string s)
        {
            List<int> indexes = new List<int>();

            for (int i = s.IndexOf('a'); i > -1; i = s.IndexOf('a', i + 1))
            {
                 // for loop end when i=-1 ('a' not found)
                indexes.Add(i);
            }

            return indexes;
        }

        private static List<int> FoundIndexesLoop(string s)
        {
            var indexes = new List<int>();
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] == 'a')
                indexes.Add(i);
            }

            return indexes;
        }
    }
}
于 2012-10-16T15:09:41.313 に答える
0

IndexOf(char value, int startIndex)次の属性でマークされています:[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]

また、このメソッドの実装は、おそらく安全でないコードを使用するか、ネイティブのFindNLSStringWin32関数を使用するなど、より「ネイティブな」手法を使用するなど、他の多くの方法で最適化される可能性があります。

于 2012-10-16T16:07:22.773 に答える