0

エスケープする文字がない場合は、

if (s.Contains("\"")) 
    s = s.Replace("\"", "\"\""); 

本当に速く走る

s = s.Replace("\"", "\"\"");

containsメソッドは、Replaceメソッドと同じように文字列を検索する必要があり、Replaceメソッドがエスケープするものを見つけられない場合は、Containsメソッドが検索するのにかかる時間よりも長くはかからないと思います。ストリング。ただし、エスケープする文字がある場合は、文字列を2回検索する必要があります。

4

7 に答える 7

4

いくつかの基本的なパフォーマンステストでは、10 000 000回ごとに(中央に引用符が付いた約30文字の文字列を使用して)、次のようになります。

Contains("\"")          1327 ms.
Contains('"')           2949 ms.
Replace("\"", "\"\"")   2528 m.s

Contains通話時間は通話時間の約半分ですReplace。文字列を探すよりも文字を探す方が速いと思いましたが、意外とそうではありません。

したがって、最初にチェックし、損益分岐点を取得するために常に置換する場合を比較します。ここで、xはContains呼び出しの時間であり、yは置換を行う必要がある頻度です。

x + 2xy = 2x

与える:

y = 0.5

これは、2つの方法が約50%でも損益分岐点になることを意味します。半分以上の時間で交換を行う必要がある場合、最初に存在を確認してもメリットはありません。

于 2012-08-30T19:09:19.377 に答える
1

Andre Calilのマイクロベンチマークが変更されました:

        List<string> StringList = new List<string>();

        for (int i = 0; i < 10000; i++)
        {
            StringList.Add(DateTime.Now.Ticks + " abc ");
        }

        string temp;

        KeyValuePair<string, string>[] StringsToReplace = new KeyValuePair<string, string>[6];

        // Use array to avoid dictionary access cost
        StringsToReplace[0] = new KeyValuePair<string,string>("1", ".1.");
        StringsToReplace[1] = new KeyValuePair<string,string>("a", "z");
        StringsToReplace[2] = new KeyValuePair<string,string>("b", "x");
        StringsToReplace[3] = new KeyValuePair<string,string>("c", "v");
        StringsToReplace[4] = new KeyValuePair<string,string>("d", "u");
        StringsToReplace[5] = new KeyValuePair<string,string>("e", "t");

        int TotalIterations = 100;
        Stopwatch stopWatch1 = new Stopwatch();
        Stopwatch stopWatch2 = new Stopwatch();

        GC.Collect(); // remove influence of garbage objects

        for (int j = 0; j <= TotalIterations; j++)
        {
            stopWatch1.Start(); // StopWatch Start/Stop does its own accumation

            for (int i = 0; i < StringList.Count; i++)
            {
                for (int k = 0; k < StringsToReplace.Length; k++)
                {
                    temp = StringList[i].Replace(StringsToReplace[k].Value, StringsToReplace[k].Key);
                }
            }

            stopWatch1.Stop();

            stopWatch2.Start();

            for (int i = 0; i < StringList.Count; i++)
            {
                for (int k = 0; k < StringsToReplace.Length; k++)
                {
                    if (StringList[i].Contains(StringsToReplace[k].Value))
                        temp = StringList[i].Replace(StringsToReplace[k].Value, StringsToReplace[k].Key);
                }
            }

            stopWatch2.Stop();

            if (j == 0) // discard first run, warm only
            {
                stopWatch1.Reset();
                stopWatch2.Reset();
            }
        }

        // Elapsed.TotalMilliseconds return in double, more accurate than ElapsedMilliseconds
        Console.WriteLine("Replace           : {0:N3} ms", stopWatch1.Elapsed.TotalMilliseconds / TotalIterations);
        Console.WriteLine("Contains > Replace: {0:N3} ms", stopWatch2.Elapsed.TotalMilliseconds / TotalIterations);

50%の時間で実際の交換が必要になるため、Replaceを直接呼び出すことになります。

Replace           : 7.453 ms
Contains > Replace: 8.381 ms
于 2012-08-31T00:08:01.150 に答える
0

これは、すべての文字列に対する修正が必要な文字列の比率によって異なります。非常に小さな文字列を修正する必要がある場合、これは確かに勝利です。一致するものが見つからない場合、Replaceは確かに新しい文字列を割り当てないため、勝利は非常に小さくなります。これは一般的な最適化です。

ただし、損益分岐点は予測できません。測定。

于 2012-08-30T18:45:41.117 に答える
0

すべてのパフォーマンス関連の質問と同様に、答えは測定です。

それは、どれだけインテリジェントでReplaceあるか(「事前に」メモリを割り当てますか?もしそうなら、パフォーマンスへの影響はどれくらいですか?)、処理する文字列の総数に対する置換が必要な文字列の比率、長さによって異なります。最初のインデックス"が配置されている文字列の(より早くContains戻ることができればより高速ですtrue)など。

于 2012-08-30T18:48:04.537 に答える
0

String.Replace

このメソッドは、通常の(大文字と小文字を区別し、カルチャを区別しない)検索を実行してoldValueを検索します。

String.Contains

このメソッドは、通常の(大文字と小文字を区別し、文化を区別しない)比較を実行します。検索は、この文字列の最初の文字位置から始まり、最後の文字位置まで続きます。

ですから、実際的な違いはないと思います。それでも、ここでマイクロベンチマークを実行します。


マイクロベンチマーク(男、私はこれが大好きです)

コード:

        List<string> StringList = new List<string>();

        for (int i = 0; i < 10000; i++)
        {
            StringList.Add(DateTime.Now.Ticks + " abc ");
        }

        string temp;

        Dictionary<string, string> StringsToReplace = new Dictionary<string, string>();
        StringsToReplace.Add("1", ".1.");
        StringsToReplace.Add("a", "z");
        StringsToReplace.Add("b", "x");
        StringsToReplace.Add("c", "v");
        StringsToReplace.Add("d", "u");
        StringsToReplace.Add("e", "t");

        long ReplaceElapsedTime = 0;
        long ContainsReplaceElapsedTime = 0;

        int TotalIterations = 10000;

        for (int j = 0; j < TotalIterations; j++)
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            for (int i = 0; i < StringList.Count; i++)
            {
                foreach (KeyValuePair<string, string> CurrentPair in StringsToReplace)
                {
                    temp = StringList[i].Replace(CurrentPair.Value, CurrentPair.Key);
                }
            }

            stopWatch.Stop();

            ReplaceElapsedTime += stopWatch.ElapsedMilliseconds;

            stopWatch.Reset();
            stopWatch.Start();

            for (int i = 0; i < StringList.Count; i++)
            {
                foreach (KeyValuePair<string, string> CurrentPair in StringsToReplace)
                {
                    if (StringList[i].Contains(CurrentPair.Value))
                        temp = StringList[i].Replace(CurrentPair.Value, CurrentPair.Key);
                }
            }

            stopWatch.Stop();

            ContainsReplaceElapsedTime += stopWatch.ElapsedMilliseconds;
        }

        Console.WriteLine(string.Format("Replace: {0} ms", ReplaceElapsedTime/TotalIterations));
        Console.WriteLine(string.Format("Contains > Replace: {0} ms", ContainsReplaceElapsedTime/TotalIterations));

        Console.ReadLine();

結果:

Replace: 14 ms 
Contains > Replace: 14 ms

=)

于 2012-08-30T18:48:45.190 に答える
0

誰かが興味を持っている場合(あなたはそうではありません、私を信じてください)、OPのメソッドをより効率的にするために置き換える必要がある文字列の必要なパーセンテージを見つけるための方程式は(大まかに)これです:

はい、そのとおり。

どこ:

C = Time it takes to create a new string
R = average Ratio of Delimiter position to string length
n = average string length
p = average position of the delimiter (quote in this case) in the string
t = time it takes to search one character of a string

したがって、引用符が含まれている文字列の割合がこれよりも大きい場合は、必ず最初の方法を使用してください。

Cこれは、戻る時間、文字の実際の置換(実際にはそれを含めることができます)、または私が知らないあらゆる種類のコンパイラ最適化など、私が無視できると考えた変数を考慮していません。

ちなみに、私が世界で最も役に立たない方程式を解くのに30分を費やしたという事実は、私が数学からCSに切り替えた理由の完璧な例です。

于 2012-08-30T18:56:07.643 に答える
0

新しいバージョン:

        string test = "A quick brown fox jumps over a lazy dog.";

        int count = 1000 * 1000;

        Stopwatch watch = new Stopwatch();

        for (int i = 0; i < 4; i++)
        {
            string result = String.Empty;

            watch.Restart();

            for (int c = 0; c < count; c++)
            {
                switch (i)
                {
                    case 0: // warmup
                        break;

                    case 1:
                        if (test.Contains("\""))
                        {
                            result = test.Replace("\"", "\"\"");
                        }
                        break;

                    case 2:
                        result = test.Replace("\"", "\"\"");
                        break;

                    case 3:
                        if (test.IndexOf('\"') >= 0)
                        {
                            result = test.Replace("\"", "\"\"");
                        }
                        break;
                }
            }

            watch.Stop();

            Console.WriteLine("Test {0,16} {1,7:N3} ms {2}", 
                new string[]{"Base","Contains-Replace","Replace","IndexOf-Replace"}[i],
                watch.Elapsed.TotalMilliseconds,
                result);

結果:

Test             Base   3.026 ms
Test Contains-Replace 284.780 ms
Test          Replace 214.503 ms
Test  IndexOf-Replace  64.447 ms

したがって、Contains(string)自体は非常に低速です。その理由は、NLS(自然言語処理APIです。ただし、IndexOf(char)の方がはるかに高速です。

于 2012-08-30T22:23:29.773 に答える