Регулярное выражение, которое гарантирует, что ни один символ не повторяется - PullRequest
3 голосов
/ 25 августа 2010

Мне нужно убедиться, что входная строка соответствует этим правилам:

  • Он должен содержать только заглавные буквы.
  • Никакой символ не должен повторяться в строке. например. ABCA недействителен, потому что повторяется «A».

В верхнем регистре хорошо, [A-Z]. Но я теряюсь в том, чтобы не повторять символы.

Может кто-нибудь предложить какой-нибудь метод с использованием регулярных выражений?

Ответы [ 6 ]

6 голосов
/ 25 августа 2010

Вы можете сделать это с помощью регулярных выражений .NET, хотя я бы посоветовал против этого:

string s = "ABCD";
bool result = Regex.IsMatch(s, @"^(?:([A-Z])(?!.*\1))*$");

Вместо этого я бы посоветовал проверить, что длина строки совпадает с количеством различных символов, и отдельно проверить требование A-Z:

bool result = s.Cast<char>().Distinct().Count() == s.Length;

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

2 голосов
/ 25 августа 2010

Использовать отрицательный прогноз и обратную ссылку.

  string pattern = @"^(?!.*(.).*\1)[A-Z]+$";
  string s1 = "ABCDEF";
  string s2 = "ABCDAEF";
  string s3 = "ABCDEBF";
  Console.WriteLine(Regex.IsMatch(s1, pattern));//True
  Console.WriteLine(Regex.IsMatch(s2, pattern));//False
  Console.WriteLine(Regex.IsMatch(s3, pattern));//False

\1 соответствует первой захваченной группе.Таким образом, отрицательный взгляд заканчивается неудачей, если любой символ повторяется.

2 голосов
/ 25 августа 2010

Почему бы не проверить наличие символа, который повторяется или нет в верхнем регистре? С чем-то вроде ([A-Z])?.*?([^A-Z]|\1)

2 голосов
/ 25 августа 2010

Это невозможно сделать с помощью регулярных выражений, поскольку они не зависят от контекста.Вам нужен хотя бы контекстно-зависимый язык грамматики, поэтому единственный способ добиться этого - написать функцию от руки.

См. формальная грамматика для теории фона.

0 голосов
/ 25 августа 2010

Это можно сделать с помощью обратного вызова.

Я программа на Java, поэтому я покажу вам, как это делается в Java (для C # см. здесь ).

final Pattern aPattern = Pattern.compile("([A-Z]).*\\1");
final Matcher aMatcher1 = aPattern.matcher("ABCDA");
System.out.println(aMatcher1.find());
final Matcher aMatcher2 = aPattern.matcher("ABCDA");
System.out.println(aMatcher2.find());

Регулярный экспресс - ([A-Z]).*\\1, что переводится как anything between 'A' to 'Z' as group 1 ('([A-Z])') anything else (.*) and group 1.

Используйте $1 для C #.

Надеюсь, это поможет.

0 голосов
/ 25 августа 2010

Это не регулярное выражение, и оно будет медленным, но вы можете создать массив содержимого строки, а затем выполнить итерацию по массиву, сравнивая n с n ++

= Уолдо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...