3

次のような文字列が与えられた場合:

string s1 = "Abc";
string s2 = "ABC";

より速いもの:

Regex.Match(s1, s2, RegexOptions.IgnoreCase)

また

s1.ToLower() == s2.ToLower()

それらが同じであるか、一方が他方よりも高速である場合、一方を他方よりも使用する方が良いのはいつですか?

4

7 に答える 7

8

おそらく2番目の方が高速ですが、これらのアプローチは両方とも避けたいと思います。

string.Equals適切なStringComparison引数を指定してメソッドを使用することをお勧めします。

s1.Equals(s2, StringComparison.CurrentCultureIgnoreCase)

オンラインでの動作を確認してください: ideone

于 2012-05-13T16:02:11.013 に答える
4

@MarkByersはすでに正しい答えを投稿しています。

文字列の比較にToLowerを使用してはならないことを強調したいと思います。正しくありません。

s1.Equals(s2, StringComparison.CurrentCultureIgnoreCase) //#1
s1.ToLower() == s2.ToLower() //#2
s1.ToLowerInvariant() == s2.ToLowerInvariant() //#3

(2)と(3)はどちらも、エキゾチックな言語や奇妙な文字に関しては正しくありません。トルコ語の「I」は古典的な例です。

ハッシュテーブルであっても、常に#1を使用してください

(非常に特別な状況を除く)

于 2012-05-13T16:12:27.537 に答える
4

理論的に言えば、2 つの文字列の比較は高速であるはずですが、RegEx はかなり遅いことが知られています。

ただし、大文字と小文字を区別せずに文字列 s1 を RegEx s2 に一致させたい場合 (これは 2 つの文字列を比較することとは異なります)、別の文字列を作成しないようにするため、最初のソリューションの方が適しています。

この種の質問ではいつものように、ベンチマークを実行して両方のパフォーマンスを比較します :)

于 2012-05-13T16:04:43.640 に答える
3

Regex.Match(s1, s2, RegexOptions.IgnoreCase)一般的な場合、大文字と小文字を区別しない同等性をチェックするのは安全な方法ではないことに注意してください。の場合を考えてみましょs2".*"Regex.Matchs1があっても常にtrueを返します!

于 2012-05-13T16:14:11.620 に答える
3

これは、私が今まで見た中で最も時期尚早な最適化の極端なケースかもしれません 。私を信じてください、この問題が関連する状況に遭遇することは決してありません.

そして、「遅いから」という理由で正規表現を避けるように言う人々の言うことを聞かないでください。 正しく書かれていない正規表現は確かにリソースをむさぼり食いますが、それは正規表現を書いた人のせいです。適度に巧妙に作成された正規表現は、人々がそれらを適用する大部分のタスクに対して十分に高速です。

于 2012-05-13T22:12:46.483 に答える
0

提案された 3 つの方法の小さな比較を次に示します。

正規表現: 282ms ToLower: 67ms Equals: 34ms

public static void RunSnippet()
{
    string s1 = "Abc";
    string s2 = "ABC";

    // Preload
    compareUsingRegex(s1, s2);
    compareUsingToLower(s1, s2);
    compareUsingEquals(s1, s2);

    // Regex
    Stopwatch swRegex = Stopwatch.StartNew();
    for (int i = 0; i < 300000; i++) 
        compareUsingRegex(s1, s2);
    Console.WriteLine(string.Format("Regex: {0} ms", swRegex.ElapsedMilliseconds));

    // ToLower
    Stopwatch swToLower = Stopwatch.StartNew();
    for (int i = 0; i < 300000; i++) 
        compareUsingToLower(s1, s2);
    Console.WriteLine(string.Format("ToLower: {0} ms", swToLower.ElapsedMilliseconds));

    // ToLower
    Stopwatch swEquals = Stopwatch.StartNew();
    for (int i = 0; i < 300000; i++) 
        compareUsingEquals(s1, s2);
    Console.WriteLine(string.Format("Equals: {0} ms", swEquals.ElapsedMilliseconds));
}

private static bool compareUsingRegex(string s1, string s2) 
{
    return Regex.IsMatch(s1, s2, RegexOptions.IgnoreCase);
}

private static bool compareUsingToLower(string s1, string s2) 
{
    return s1.ToLower() == s2.ToLower();
}

private static bool compareUsingEquals(string s1, string s2) 
{
    return s1.Equals(s2, StringComparison.CurrentCultureIgnoreCase);
}
于 2012-05-13T21:55:32.043 に答える
0

比較は高速になりますが、小文字または大文字に変換してから比較する代わりに、大文字と小文字を区別しない等価比較を使用することをお勧めします。例:

        s1.Equals(s2, StringComparison.OrdinalIgnoreCase)
于 2012-05-13T17:41:03.450 に答える