2016-09-20 5 views
1

Мне нужно проверить серийные номера, и одно из правил состоит в том, что допускается до 5 смежных равных символов.Подсчитайте количество смежных равных символов

Пример действует:

012W212222123 // 4x the digit 2 contiguous 

Пример недействителен:

012W764444443 // 6x the digit 4 

Так что я пытался получить максимальное количество последовательных символов без успеха

int maxCount = "012W764444443".GroupBy(x => x).Max().Count(); 
+5

Почему бы не использовать регулярное выражение для этого? 'Regex.IsMatch (ввод, @ "^ (?!. * ([0-9]) \ 1 {4})") '? Если вам нужно проверить * любые * символы, а не только цифры, используйте '.' вместо' [0-9] ' –

+0

Для дальнейшего уточнения -' GroupBy' не будет работать, потому что он будет группировать * все * символы в string, а не только те, которые находятся рядом друг с другом. Если вы не хотите создавать свою собственную версию группировки, которая также учитывает позицию, правильно сформированное регулярное выражение, как было предложено Wiktor, было бы проще. – kiziu

ответ

4

Я предлагаю использовать регулярное выражение для проверьте, есть ли 5 ​​или более последовательных цифр:

Regex.IsMatch(input, @"^(?!.*([0-9])\1{4})") 

Если какие-либо символы предназначены:

Regex.IsMatch(input, @"^(?!.*(.)\1{4})") 

См regex demo

Регулярное выражение находит совпадение в строке, которая содержит менее чем 5 одинаковых последовательных цифр (версия с [0-9]) или любые символы кроме новой строки (версия с .).

Детали:

  • ^ - начало строки - (?!.*(.)\1{4}) - отрицательный предпросмотр, который не проходит матч, если шаблон сопоставляется:
    • .* - любые 0+ другие, чем CHARS newline
    • (.) - Группа 1, захватывающая любой символ, но символ новой строки
    • \1{4} - ровно 4 последовательных вхождения одного и того же значения, хранящегося внутри группы 1 (где \1 является backreference и {4} является range/bound/limiting quantifier).

C#:

var strs = new List<string> { "012W212222123", "012W764444443"}; 
    foreach (var s in strs) 
     Console.WriteLine("{0}: {1}", s, Regex.IsMatch(s, @"^(?!.*(.)\1{4})")); 
2

Еще один вариант, чтобы использовать эту функцию:

public static int MaxNumberOfConsecutiveCharacters(string s) 
{ 
    if (s == null) throw new ArgumentNullException(nameof(s)); 

    if (s.Length == 0) return 0; 

    int maxCount = 1; 
    int count = 1; 

    for (int i = 1; i < s.Length; i++) 
    { 
     if (s[i] == s[i-1]) 
     { 
      count++; 
      if (count > maxCount) maxCount = count; 
     } 
     else 
     { 
      count = 1; 
     } 
    } 

    return maxCount; 
} 

Очевидно, что это намного больше кода, чем регулярное выражение. В зависимости от ваших знаний о регулярных выражениях это может быть или не быть более читаемым для вас. Кроме того, это, вероятно, более эффективно, чем использование регулярного выражения, которое может или не может быть важно для вас.

2

Это немного неэффективно, но это работает:

var max = 
    "012W212222123" 
     .Aggregate(
      new { Char = ' ', Count = 0, Max = 0 }, 
      (a, c) => 
       a.Char == c 
        ? new { Char = c, Count = a.Count + 1, Max = a.Max > a.Count + 1 ? a.Max : a.Count + 1 } 
        : new { Char = c, Count = 1, Max = a.Max > 1 ? a.Max : 1 }) 
     .Max; 

Я попытался с обоих входов и получил правильное число максимальных повторений каждый раз.

Смежные вопросы