开发者

what is the fastest way to check whether string has uppercase letter in c#?

开发者 https://www.devze.com 2023-03-09 09:42 出处:网络
My first implementation idea is to do simply: bool hasUpperCase (string str) { if(string.IsNullOrEmpty(str))

My first implementation idea is to do simply:

bool hasUpperCase (string str) {
    if(string.IsNullOrEmpty(str))
         开发者_JS百科return false;
    for (int i = 0; i < str.Length; i++) {
        if (char.IsUpper (str[i]))
            return true;                    
    }
    return false;
}

but maybe there is another faster way to do that ?


You could reduce that to

bool HasUpperCase (string str) {
    return !string.IsNullOrEmpty(str) && str.Any(c => char.IsUpper(c));
}

using LINQ.


Cheating from here:

bool hasUpperCase (string str) {
 if(string.IsNullOrEmpty(str))
     return false;

  return str != str.ToLower();
}


ok - time for the new truth!

This was a test for any upper case character in a string.

The string was guaranteed to not have any upper case character within the first 60K of characters. (I created the string from random.org)

I prevented string substitution optimization in the compiler by randomizing which 64K character string was passed to the test function.

All timings were very strictly around the actual test, and did not include function calling time.

I ran the test once, 10 times, and again for 10,000 times and averaged each set of the timings for each test.

I ran the test on a 64bit Win 7 with i3-2100 CPU @ 3.1 Ghz

Test Case 1:

   static bool testCaseOne(string str, out double ms)
    {
        bool result = false;
        DateTime start = DateTime.Now;

        result = !string.IsNullOrEmpty(str) && str.Any(c => char.IsUpper(c));
        ms = (DateTime.Now - start).TotalMilliseconds;
        return result;
    }

Resulting average time:

  1. 1 X = 3.000 ms
  2. 10 x = 0.860 ms
  3. 10,000 x = 0.821 ms

Test Case 2:

    static bool testCaseTwo(string str, out double ms)
    {
        bool result = false;
        DateTime start = DateTime.Now;

        if (string.IsNullOrEmpty(str))
        {
            ms = 0;
            return false;
        }
        result = Regex.IsMatch(str, "[A-Z]");

        ms = (DateTime.Now - start).TotalMilliseconds;

        return result;
    }

Resulting average time:

  1. 1 x = 2.000 ms
  2. 10 x = 1.597 ms
  3. 10,000 x = 1.603 ms

Test Case 3:

   static bool testCaseThree(string str, out double ms)
    {
        bool result = false;
        DateTime start = DateTime.Now;

        if (string.IsNullOrEmpty(str))
        {
            ms = 0;
            return false;
        }
        for (int i = 0; i < str.Length; i++)
        {
            if (char.IsUpper(str[i]))
            {
                result = true;
                break;
            }
        }
        ms = (DateTime.Now - start).TotalMilliseconds;
        return result;
    }

Resulting average time:

  1. 1 x = 1.000 ms
  2. 10 x = 0.357 ms
  3. 10,000 x = 0.298 ms

Test Case 4:

    static bool testCaseFour(string str, out double ms)
    {
        bool result = false;
        DateTime start = DateTime.Now;

        if (string.IsNullOrEmpty(str))
        {
            ms = 0;
            return false;
        }
        for (int i = 0; i < str.Length; i++)
        {

            if (str[i] > 64 && str[i] < 91)
            {
                result = true;
                break;
            }
        }
        ms = (DateTime.Now - start).TotalMilliseconds;
        return result;
    }

}

Resulting average time:

  1. 1 x = 0.000 ms
  2. 10 x = 0.137 ms
  3. 10,000 x = 0.184 ms

Interesting.

I hope this statisfies Mr. R. K. ;)


bool hasUpperCase(string str) {
    if (string.IsNullOrEmpty(str))
        return false;
    return Regex.IsMatch(str, "[A-Z]");
}

Disclaimer: I am no Regex expert but I tested this with the strings Testing, testinG, and tesTing, which all evaluated to true. However, it also evaluated to true with the string TESTING, which you may or may not want.


The code looks fine to me, since you ask for performance, you can reduce the for loop from O(n) to O(n/2 + ~1) by adding the conditional checking from the reverse side.

Otherwise you can check two sub-sequent elements and increment the i by 2. Obviously you should check for i < str.Length for the second argument.

bool hasUpperCase (string str) {
if(string.IsNullOrEmpty(str))
     return false;
for (int i = 0; i < str.Length; i= i + 2) {
    if (char.IsUpper (str[i]))
        return true;                    

    if ((i + 1) < str.Length && char.IsUpper (str[i+1]))
        return true;                    
}
return false;

}

IMHO, this tip may help to answer algorithm interview, doesn't get much performance.


    public static string Upper_To_Lower(string text)
    {
        if (Char.IsUpper(text[0]) == true) { text = text.Replace(text[0], char.ToLower(text[0])); return text; }

        return text;
    }

    public static string Lower_To_Upper(string text)
    {
        if (Char.IsLower(text[0]) == true) { text = text.Replace(text[0], char.ToUpper(text[0])); return text; }

        return text;
    }

Here i made 2 simple methods who check the first letter of any string and convert it from Upper to Lower and virse verca .... hope that will help you.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号