web-dev-qa-db-fra.com

quel est le moyen le plus rapide de vérifier si la chaîne a une lettre majuscule en c #?

Ma première idée d'implémentation est de faire simplement:

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

mais peut-être existe-t-il un autre moyen plus rapide de le faire?

21
tomaszkubacki

Vous pourriez réduire cela à

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

en utilisant LINQ.

40
Femaref

Tricher à partir d'ici:

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

  return str != str.ToLower();
}
9
Peter K.

ok - l'heure de la nouvelle vérité!

C'était un test pour tout caractère majuscule dans une chaîne.

Il était garanti que la chaîne ne contiendrait aucune majuscule dans les 60 000 premiers caractères. (J'ai créé la chaîne de random.org)

J'ai empêché l'optimisation de la substitution de chaînes dans le compilateur en sélectionnant au hasard la chaîne de caractères de 64 Ko transmise à la fonction de test.

Tous les temps étaient très strictement liés au test et n'incluaient pas le temps d'appel des fonctions.

J'ai effectué le test une fois, 10 fois et encore 10 000 fois et en moyenne chaque ensemble de minutages pour chaque test.

J'ai couru le test sur un Windows 7 64bits avec i3-2100 CPU à 3.1 Ghz

Cas de test 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;
    }

Temps moyen résultant:

  1. 1 X = 3 000 ms
  2. 10 x = 0,860 ms
  3. 10 000 x = 0,821 ms

Cas de test 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;
    }

Temps moyen résultant:

  1. 1 x = 2 000 ms
  2. 10 x = 1,597 ms
  3. 10 000 x = 1,603 ms

Cas de test 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;
    }

Temps moyen résultant:

  1. 1 x = 1.000 ms
  2. 10 x = 0,357 ms
  3. 10 000 x = 0,298 ms

Cas de test 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;
    }

}

Temps moyen résultant:

  1. 1 x = 0,000 ms
  2. 10 x = 0,137 ms
  3. 10 000 x = 0,184 ms

Intéressant.

J'espère que cela répond à MR K.;)

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

Disclaimer : Je ne suis pas un expert de Regex, mais j'ai testé cela avec les chaînes Testing, testinG, and tesTing, qui ont toutes été évaluées comme étant vraies. Cependant, il a également été évalué à true avec la chaîne TESTING, que vous souhaitiez ou non.

3
aligray

Le code me semble bien, puisque vous demandez des performances, vous pouvez réduire la boucle for de O(n) à O (n/2 + ~ 1) en ajoutant la vérification conditionnelle du verso.

Sinon, vous pouvez vérifier les deux éléments suivants et incrémenter le i de 2. Évidemment, vous devez vérifier i <str.Length pour le deuxième 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, cette astuce peut aider à répondre à l'interview algorithmique, n'obtient pas beaucoup de performances.

2
user90150
    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;
    }

Ici, j’ai fait 2 méthodes simples pour vérifier la première lettre d’une chaîne et la convertir de Upper à Lower et virse verca .... espérons que cela vous aidera.

0
Antho