11
votes

Combinant ces deux expressions régulières en un

J'ai ce qui suit dans c #: xxx

Je veux vérifier si le paramètre s contient au moins un caractère alphabétique et un chiffre et j'ai écrit la méthode ci-dessus pour le faire.

mais y a-t-il une façon de combiner les deux expressions régulières ( "[a-za-z] +" et < code> "\ d +" ) en un?


4 commentaires

Si vous souhaitez simplement vérifier au moins 1 d'entre eux, n'utilisez pas l'opérateur + pour correspondre à une chaîne inutilement plus longue.


Je pense que la version originale est plus élégante et lisible que la plupart des réponses.


Il me semble que cette méthode devrait être appelée hasalphaenumérique . Vous ne vérifiez que cela contient un de chacun; Le reste des personnages pourrait être n'importe quoi, ou rien. Par exemple, A1 et ! @ # 1% ^ & a () _ passe-bas - est-ce ce que vous avez voulu?


@Alan Moore: Oui, vous êtes correct; Votre nom de méthode suggéré est meilleur que le mien.


6 Réponses :


2
votes
private static readonly Regex _regex = new Regex(
    @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$", RegexOptions.Compiled);

public static bool IsAlphaAndNumeric(string s)
{
    return _regex.IsMatch(s);
}
If you want to ignore case you could use RegexOptions.Compiled | RegexOptions.IgnoreCase.

4 commentaires

Pour op, recherche positive lookahead sur cette page: MSDN.MicRosoft .Com / fr-US / bibliothèque / 1400241x (vs.85) .aspx


Cette regex ne correspond que des chaînes contenant une lettre minuscule et une lettre majuscule ...


En outre, il nécessitera soit des expulsions de réégytoption.singline ou non des chaînes correspondant à une nouvelle ligne avant l'un des trois caractères requis (lettre majuscule, lettre minuscule et numéro)


Si vous passez regexoption.ignorecase il n'y a pas besoin d'avoir le (? =. * [A-Z]) Lookahead.



3
votes

Vous pouvez utiliser [a-za-z]. * [0-9] | [0-9]. * [A-ZA-Z] , mais je ne le recommanderais que Si le système que vous utilisiez uniquement a accepté une seule regex. Je ne peux pas imaginer que cela serait plus efficace que deux modèles simples sans alternance.


0 commentaires

12
votes
@"^(?=.*[a-zA-Z])(?=.*\d)"

 ^  # From the begining of the string
 (?=.*[a-zA-Z]) # look forward for any number of chars followed by a letter, don't advance pointer
 (?=.*\d) # look forward for any number of chars followed by a digit)
Uses two positive lookaheads to ensure it finds one letter, and one number before succeding.   You add the ^ to only try looking forward once, from the start of the string.  Otherwise, the regexp engine would try to match at every point in the string.

0 commentaires

3
votes

Ce n'est pas exactement ce que vous voulez mais laissez-vous dire que j'ai plus de temps. Vous devez suivre plus rapidement que la regex.

My solution : 00:00:00.3900390 (Goody Gold Medal)
DarinDimitrov  1 : 00:00:00.9740974 (Bronze Medal)
DarinDimitrov(compiled) 2 : 00:00:00.8230823 (Silver)


10 commentaires

Toute justification pourquoi cela serait plus rapide que la regex?


Et si c'est est plus rapide, la différence sera triviale. Vous devriez tester des millions de cordes dans une boucle serrée pour que cela vaut la peine.


J'ai publié le résultat de la performance. Dans ma réponse. Dit que tu as eu le temps.


C'est merveilleux. Sauf que la solution de Darin n'est même pas correcte - elle cherche des majuscules et des minuscules.


Hmm n'a pas remarqué cela. Mais la conclusion est que la regex compilée est plus rapide, même si elle nécessite une compilation initiale de l'assemblage par .NET Framework et devrait être effectuée dans un constructeur statique. Quelqu'un peut-il s'améliorer sur le mien?


Pouvez-vous s'il vous plaît essayer la réégycle que j'ai fournie comme une version compilée dans vos tests PERF? @ "^ (? =. * [A-Z] [A-Z]) (? =. * \ d)"


Aussi - votre version vérifie que tous les caractères sont des chiffres ou des chiffres ... L'OP est uniquement testé qu'il possède un caractère alpha et un caractère numérique ... peut-être essayer de régler votre boucle pour retourner vrai une fois qu'il trouve un de chacun. Pourrait rattraper les versions compilées Regexp (qui ne vérifient pas la chaîne entière, elles parcourent une lettre, puis numérisent pour un numéro. Le pire cas de test pour ceci est une chaîne qui contient une lettre à la fin, et aucun chiffre, il prendra le plus de temps dans le moteur Regeuxp


@gnarf vous avez raison mon one surperformé. Vérifiez les résultats que je l'ai mis à jour.


Quelle est la performance du temps en matière de maintien de cette monstruosité?


@affan - pourquoi garder la ou les versions inexactes autour? Aucune des fonctions mentionnées dans la moitié supérieure de votre réponse fait ce que l'OP voulait, je voudrais simplement réécrire / le tester à l'aide de méthodes qui renvoient les bonnes réponses.



15
votes

pour C # avec LINQ:

return s.Any(Char.IsDigit) && s.Any(Char.IsLetter);


5 commentaires

Cela nécessitera deux itérations complètes des charges de cordes dans le cas pire.


@affan - dans le pire des cas, vous devez vérifier à deux reprises chaque personnage; Ceci est vrai pour chaque solution possible. Qu'il s'agisse d'une boucle ou de deux ne fait aucune différence, de côté de créer un autre charme itérateur - pour une chaîne en mémoire, il s'agit d'une infiltration minuscule au maximum.


@affan - Veuillez lire les instructions avant de basculer et vérifier la fonction d'origine. Il dit "au moins un caractère alphabétique et un chiffre". Vous êtes celui avec le mauvais code, car @gnarf vous a expliqué.


Si l'OP n'est pas engagé à utiliser une regex, c'est probablement la meilleure suggestion.


+1 Bien que ce soit une façon très concise et propre de le faire, je ne peux pas l'accepter parce que je demandais une expression régulière. Je vous ai toujours donné un +1 à cause de la montrage de l'alternative LINQ.



0
votes

Ce qui suit n'est pas seulement plus rapide que les autres constructions de lookahead, elle est également (dans mes yeux) plus près des exigences: xxx

sur mon (test cerf brut) à propos de La moitié du temps requis par les autres solutions de regex et présente l'avantage qu'il ne se souciera pas des nouvelles lignes dans la chaîne d'entrée. (Et si, pour une raison quelconque, il devrait, il est évident comment l'inclure).

Voici comment (et pourquoi) fonctionne:

Étape 1: Il correspond à un seul caractère (Appelons-le c ) qui est un nombre ou une lettre.
Étape 2: Il faut vérifier si c est un nombre. Si oui:
Étape 2.1: Il permet un nombre illimité de caractères qui ne sont pas une lettre, suivie d'une seule lettre. Si cela correspond, nous avons un numéro ( c ) suivi d'une lettre.
Étape 2.2: Si C n'est pas un nombre, il doit s'agir d'une lettre (sinon, cela n'aurait pas été correspondant). Dans ce cas, nous autorisons un nombre illimité de non-chiffres, suivi d'un seul chiffre. Cela signifierait que nous avons une lettre ( c ) suivie d'un numéro.


5 commentaires

Logiquement, cela est similaire à la réponse anonyme, mais plus complexe. Êtes-vous sûr que cela est rapide? En cas d'échec, il ne testerait-il pas pour chaque lettre de correspondance? (Par exemple, 600 'x's)


Comme avec la réponse de @ ASFAN, il est extrêmement improbable que cela vaut l'effort de toute façon. Les gens tentent trop de choses sur la performance des regex.


@ Anonyme Réponse correspondra à n'importe quel personnage avant la première lettre deux fois si la première branche échoue, puisque la deuxième branche fait une backtrack jusqu'au tout début. Si vous pouvez être raisonnablement sûr que la chaîne d'entrée a une lettre proche du début, elle se traduira par la même performance (et après avoir remplacé les points même avec le même sens). - Merci également d'avoir mis dans le caret manquant - aucune idée de la façon dont j'ai tué cela pendant la publication;)


Oh, et pour vous inquiéter des performances de regex: je suis ici pour le plaisir, pas pour Bucks;)


Vous pouvez éviter tout le problème du raccordement en arrière par prépension ^ (?> [^ A-za-z0-9] *) à la regex. Avec cela fait, je pense que la lunette de regarder ne tirerait plus son poids. Pour une performance maximale, j'irais avec ^ (?> [^ A-ZA-Z0-9] *) (?: [A-ZA-Z] (?> [^ 0-9] *) [ 0-9] | [0-9] (?> [^ A-ZA -Z] *) [A-ZA-Z]) . Si j'étais inquiet pour la performance, c'est ...;)