将字符串与Regex与IgnoreCase或字符串的ToLower方法进行比较是否更快?

时间:2012-05-13 16:00:31

标签: c# regex

给出这样的字符串:

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

什么更快:

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

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

如果它们相同或者一个比另一个快,那么当它更好地使用一个而不是另一个时?

7 个答案:

答案 0 :(得分:8)

可能第二个更快,但我会避免这两种方法。

最好将方法string.Equals与适当的StringComparison参数一起使用:

s1.Equals(s2, StringComparison.CurrentCultureIgnoreCase)

查看在线工作:ideone

答案 1 :(得分:4)

从理论上讲,比较2个字符串应该更快,RegEx被认为是相当慢的。

但是,如果你想在忽略大小写的情况下将字符串s1与RegEx s2匹配(这与比较2个字符串不同),那么第一个解决方案更好,因为它应该避免创建另一个字符串。

与往常一样,我会运行一个基准并比较两种表现:)

答案 2 :(得分:4)

@Mark Byers已经发布了正确答案。

我想强调你应该从不使用ToLower进行字符串比较。这是不正确的。

s1.Equals(s2, StringComparison.CurrentCultureIgnoreCase) //#1
s1.ToLower() == s2.ToLower() //#2
s1.ToLowerInvariant() == s2.ToLowerInvariant() //#3
当涉及到外来语言和奇怪的人物时,

(2)和(3)都是不正确的。土耳其语“I”是典型的例子。

始终使用#1 ,即使在Hashtables

中也是如此

(非常特殊情况除外)

答案 3 :(得分:3)

应该注意的是,在一般情况下,Regex.Match(s1, s2, RegexOptions.IgnoreCase)不是检查不区分大小写的相等的安全方法。考虑s2".*"的情况。无论Regex.Match是什么,s1总会返回true!

答案 4 :(得分:3)

这可能是我见过的premature optimization最极端的情况。相信我,你永远不会遇到这个问题相关的情况。

不要听那些告诉你要避免正则表达的人,因为“他们很慢”。 写得不好的正则表达式确实可以让资源变得非常糟糕,但这是编写正则表达式的人的错。合理精心制作的正则表达式足够快,足以满足人们应用它们的绝大多数任务。

答案 5 :(得分:0)

比较会更快,但不是转换为大写或大写,然后进行比较,最好使用可以不区分大小写的相等比较。例如。 :

        s1.Equals(s2, StringComparison.OrdinalIgnoreCase)

答案 6 :(得分:0)

以下是对3种方法的一个小比较:

  

正则表达:282ms   ToLower:67ms   相等:34毫秒

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);
}