Es ist nicht genau das, was Sie wollen, aber lassen Sie mich sagen, ich habe mehr Zeit. Folgendes sollte schneller als Regex funktionieren.
static bool IsAlphaAndNumeric(string str) {
bool hasDigits = false;
bool hasLetters=false;
foreach (char c in str) {
bool isDigit = char.IsDigit(c);
bool isLetter = char.IsLetter(c);
if (!(isDigit | isLetter))
return false;
hasDigits |= isDigit;
hasLetters |= isLetter;
}
return hasDigits && hasLetters;
}
Warum ist es schnell lassen Sie es auschecken. Folgendes ist der Test-String-Generator. Es erzeugt 1/3 der vollständig korrekten Zeichenfolge und 2/3 der falschen Anzeige. In 2/3 1/2 sind alle Buchstaben und in der anderen Hälfte alle Ziffern.
static IEnumerable<string> GenerateTest(int minChars, int maxChars, int setSize) {
string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
string numbers = "";
Random rnd = new Random();
int maxStrLength = maxChars-minChars;
float probablityOfLetter = 0.0f;
float probablityInc = 1.0f/setSize;
for (int i = 0; i < setSize; i++) {
probablityOfLetter = probablityOfLetter + probablityInc;
int length = minChars + rnd.Next() % maxStrLength;
char[] str = new char[length];
for (int w = 0; w < length; w++) {
if (probablityOfLetter < rnd.NextDouble())
str[w] = letters[rnd.Next() % letters.Length];
else
str[w] = numbers[rnd.Next() % numbers.Length];
}
yield return new string(str);
}
}
Folgendes ist Darin zwei Lösung. Einer hat kompiliert und andere sind nicht kompilierte Version.
class DarinDimitrovSolution
{
const string regExpression = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$";
private static readonly Regex _regex = new Regex(
regExpression, RegexOptions.Compiled);
public static bool IsAlphaAndNumeric_1(string s) {
return _regex.IsMatch(s);
}
public static bool IsAlphaAndNumeric_0(string s) {
return Regex.IsMatch(s, regExpression);
}
Im Anschluss an die Haupt der Testschleife
static void Main(string[] args) {
int minChars = 3;
int maxChars = 13;
int testSetSize = 5000;
DateTime start = DateTime.Now;
foreach (string testStr in
GenerateTest(minChars, maxChars, testSetSize)) {
IsAlphaNumeric(testStr);
}
Console.WriteLine("My solution : {0}", (DateTime.Now - start).ToString());
start = DateTime.Now;
foreach (string testStr in
GenerateTest(minChars, maxChars, testSetSize)) {
DarinDimitrovSolution.IsAlphaAndNumeric_0(testStr);
}
Console.WriteLine("DarinDimitrov 1 : {0}", (DateTime.Now - start).ToString());
start = DateTime.Now;
foreach (string testStr in
GenerateTest(minChars, maxChars, testSetSize)) {
DarinDimitrovSolution.IsAlphaAndNumeric_1(testStr);
}
Console.WriteLine("DarinDimitrov(compiled) 2 : {0}", (DateTime.Now - start).ToString());
Console.ReadKey();
}
Es folgt ergibt
My solution : 00:00:00.0170017 (Gold)
DarinDimitrov 1 : 00:00:00.0320032 (Silver medal)
DarinDimitrov(compiled) 2 : 00:00:00.0440044 (Gold)
So ist die erste Lösung, die beste war. Einige führen mehr im Release-Modus und folgende spec
int minChars = 20;
int maxChars = 50;
int testSetSize = 100000;
My solution : 00:00:00.4060406
DarinDimitrov 1 : 00:00:00.7400740
DarinDimitrov(compiled) 2 : 00:00:00.3410341 (now that very fast)
ich wieder mit RegexOptions.IgnoreCase Flagge geprüft. Rest param wie oben
My solution : 00:00:00.4290429 (almost same as before)
DarinDimitrov 1 : 00:00:00.9700970 (it have slowed down)
DarinDimitrov(compiled) 2 : 00:00:00.8440844 (this as well still fast but look at .3 in last result)
Nach gnarf erwähnen, dass es ein Problem mit meinem algo war es überprüft wurde nur, wenn der String von Buchstaben und Ziffern bestehen, so kann ich es ändern, und es jetzt die Zeichenfolge überprüfen hat atleast eine char und eine Ziffer.
static bool IsAlphaNumeric(string str) {
bool hasDigits = false;
bool hasLetters = false;
foreach (char c in str) {
hasDigits |= char.IsDigit(c);
hasLetters |= char.IsLetter(c);
if (hasDigits && hasLetters)
return true;
}
return false;
}
Ergebnisse
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)
Meins ist schnell von einem großen Faktor.
Wenn Sie nur bestätigen wollen, dass mindestens 1 davon vorhanden ist, verwenden Sie den Operator '+' nicht, um eine unnötig lange Zeichenfolge zu finden. – kennytm
Ich denke, die ursprüngliche Version ist eleganter und lesbarer als die meisten Antworten. – Kobi
Scheint mir, diese Methode sollte ** HasAlphaAndNumeric ** genannt werden. Du überprüfst nur, dass es * einen von jedem * enthält; Der Rest der Charaktere könnte alles oder nichts sein. Zum Beispiel, 'A1' und'! @ # 1%^& A() _ 'beide bestanden - ist das, was Sie beabsichtigten? –