У меня есть следующее в C#:
public static bool IsAlphaAndNumeric(string s)
{
return Regex.IsMatch(s, @"[a-zA-Z]+")
&& Regex.IsMatch(s, @"\d+");
}
Я хочу проверить если параметр s
содержит по крайней мере один алфавитный символ и одну цифру, и я записал вышеупомянутый метод, чтобы сделать так.
Но есть ли способ, которым я могу объединить эти два регулярных выражения ("[a-zA-Z]+"
и "\d+"
) в одного?
@"^(?=.*[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)
Использует два положительного просмотра , чтобы убедиться, что он находит одну букву и одну цифру перед успешным выполнением. Вы добавляете ^
, чтобы попытаться смотреть вперед только один раз, с начала строки. В противном случае механизм регулярных выражений будет пытаться найти соответствие в каждой точке строки.
для C # с LINQ:
return s.Any(Char.IsDigit) && s.Any(Char.IsLetter);
Учебные пособия и статьи для разработчиков ОС .
-121--2087878- Можно использовать [a-zA-Z]. * [0-9] | [0-9]. * [a-zA-Z]
, но я бы рекомендовал его только в том случае, если система, которую вы использовали, принимала только один регекс. Я не могу представить, что это было бы эффективнее, чем два простых узоров без чередования.
Это не совсем то, что вы хотите, но скажем, у меня больше времени. Следующее должно работать быстрее, чем 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;
}
Почему его быстро давайте проверим это. Ниже приведен тестовый строковый генератор. Он генерирует 1/3 установленного комплектной правильной строки и 2/3 AD неверно. В 2/3 1/2 - все альфы и другая половина - все цифры.
static IEnumerable<string> GenerateTest(int minChars, int maxChars, int setSize) {
string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
string numbers = "0123456789";
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);
}
}
Следующее является Дарин Два решения. Один скомпилирован, а другая - незнаваемая версия.
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);
}
Ниже приведены основной из тестовой петли
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();
}
, следующие результаты
My solution : 00:00:00.0170017 (Gold)
DarinDimitrov 1 : 00:00:00.0320032 (Silver medal)
DarinDimitrov(compiled) 2 : 00:00:00.0440044 (Gold)
, поэтому первое решение было лучшим. Еще несколько результат в режиме выпуска и следующим спецификациям
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)
Я снова проверил с флагом RegeXOptions.ignerecase. Остальный параметр такой же, как указано выше
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)
После того, как Гнарф упомянул, что возникла проблема с моим ALGO, было проверять, если строка состоит только из буквы и цифр, поэтому я изменяю его, и теперь это проверяет, что String Show one Atleast One One Char и одна цифра.
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;
}
Результаты
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)
Мой быстрый по большому фактору.
? троичный оператор
равен
if( motion == 'pos' ) { return -distance; } else { return distance; } // - is just negating the distance value
-121--4378809- private static readonly Regex _regex = new Regex(
@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$", RegexOptions.Compiled);
public static bool IsAlphaAndNumeric(string s)
{
return _regex.IsMatch(s);
}
Если вы хотите игнорировать регистр, можно использовать RegexOptions.Compiled | RegexOptions.IgnityCase
.
Ниже приведен не только быстрее, чем другие конструкции lookahead, оно также (в моих глазах) ближе к требованиям:
[a-zA-Z\d]((?<=\d)[^a-zA-Z]*[a-zA-Z]|[^\d]*\d)
на моем (по общему признанию Решения, и имеет то преимущество, что оно не позаботится о номиналах в входной строке. (И если по какой-то причине это должно, очевидно, как его включить).
Вот как работает как (и почему):
Шаг 1: он соответствует одному символу (давайте назовим его C ), который является числом или буквой.
Шаг 2: Это делает вид, чтобы проверить, есть ли . Если так:
Шаг 2.1: Это позволяет неограниченному количеству символов, которые не являются буквой, а затем одна буква. Если это соответствует, у нас есть номер ( C ), а затем письмо.
Шаг 2.2: Если C C не является числом, оно должно быть буква (в противном случае его не было бы совпадать). В этом случае мы допускаем неограниченное количество неисследованных, а затем одной цифрой. Это означало бы, что у нас есть письмо ( C ), а затем номер.