No es exactamente lo que quieres, pero digamos que tengo más tiempo. Lo siguiente debería funcionar más rápido que regex.
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;
}
Por qué es rápido de verlo. A continuación se muestra el generador de cadena de prueba. Genera 1/3 del conjunto cadena completamente correcta y 2/3 anuncio incorrecto. En 2/3 1/2 están todos los alfos y la otra mitad son todos los dígitos.
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);
}
}
El siguiente es darin two solution. Uno ha compilado y el otro es una versión no compilada.
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);
}
siguiente es el principal del bucle de prueba
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();
}
A continuación se presenta resultados
My solution : 00:00:00.0170017 (Gold)
DarinDimitrov 1 : 00:00:00.0320032 (Silver medal)
DarinDimitrov(compiled) 2 : 00:00:00.0440044 (Gold)
Así que la primera solución era la mejor. Algunos más Resultado en modo de lanzamiento y siguiendo las especificaciones
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)
he comprobado una vez más con la bandera RegexOptions.IgnoreCase. resto del parámetro igual al anterior
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)
Después gnarf mencionar que había un problema con mi algo que estaba verificando si la cadena consiste solamente en letra y dígitos por lo que lo cambio y ahora es comprobar que muestran cadena tiene al menos con un carácter y un dígito.
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;
}
Resultados
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)
mina es rápido por un factor grande.
Si solo quiere verificar que al menos una de ellas exista, no use el operador '+' para hacer coincidir una cadena innecesariamente más larga. – kennytm
Creo que la versión original es más elegante y legible que la mayoría de las respuestas. – Kobi
Me parece que este método se debe llamar ** HasAlphaAndNumeric **. Solo está comprobando que * contiene * uno de cada uno; el resto de los personajes podría ser cualquier cosa, o nada. Por ejemplo, 'A1' y'! @ # 1%^& A() _ 'ambos pasan, ¿es eso lo que pretendías? –