Получить параметры из строки - PullRequest
0 голосов
/ 03 апреля 2019

Есть ли простой метод для проверки 2 строк, если они содержат один и тот же параметр?

Пример:

  • ReferenceString = "что-то {0} {1} {2: X}"

  • String2 = "что-то еще {0} {1} {2: X}"

  • String3 = "что-то еще {0} {0} {2: X}"

  • String4 = "что-то еще {0} {1} {2}"

  • String5 = "что-то еще {0} {1}"

Итак, мне нужно проверить:

  1. Пример: все строки содержат одинаковое количество параметров Отсутствует строка 5 {2: X}
  2. Что опечатка параметра также правильна, как String3 два раза {0} {0} вместо {0} {1}
  3. Формат также является тем же примером String4, последний параметр не правильный.

Мне не нужно указывать, что не так, просто общая проверка, например, возвращает true, если то же самое, или возвращает false, если не так

Что я делаю, так это конвертирую строку в CharaArray, затем прохожу всю чару и т. Д., Что я считаю не лучшим решением

1 Ответ

0 голосов
/ 03 апреля 2019

Вы можете извлечь все параметры с помощью регулярного выражения {(?<parameter>.+?)}.Он будет соответствовать открывающей фигурной скобке {, а затем любому количеству символов (как можно меньше) перед закрывающей фигурной скобкой }.

После этого вы можете сгруппировать все найденные параметры, и если существует только одна группа, котораяозначает, что параметры одинаковы.Чтобы сгруппировать по совокупности строк, вам нужно определить пользовательский компаратор равенства:

public class CustomEqualityComparer : IEqualityComparer<List<string>>
{
    public bool Equals(List<string> x, List<string> y)
    {
        if (x == null && y == null)
            return true;

        if (x == null || y == null)
            return false;

        return x.Count == y.Count && 
          x.Select((s, i) => (s: s, i: i)).All(t => t.s.Equals(y[t.i]));
    }

    public int GetHashCode(List<string> obj)
    {
        return obj.Aggregate(293, (c, n) => c ^ n.GetHashCode());
    }
}

Использование:

var input = new[]
{
    "something {0} {1} {2:X}",
    "something else {0} {1} {2:X}",
    "something else {0} {0} {2:X}",
    "something else {0} {1} {2}",
    "something else {0} {1}",
};

var regex = new Regex("{(?<parameter>.+?)}");

var parameters = input
    .Select(i => 
        regex.Matches(i)
            .Cast<Match>()
            .Select(m => m.Groups["parameter"].Value)
            .ToList()
        )
    .GroupBy(x => x, new CustomEqualityComparer());

var areSame = parameters.Count() == 1;

Если вы определяете свой ввод как

var input = new[]
{
    "a {0} b {1} c",
    "{0} {1}",
};

areSame будет правдой

Редактировать :

Если ваши входные строки взяты из первого аргумента string.Format или Console.Write, то (как сказано в комментарии canton7 ) они могут содержать escape-символыкак {{not a parametr}}.Если это ваш случай, вам нужно изменить регулярное выражение на

(?<!{){(?!{)(?<parametr>.+?)}

Объяснение:

(?<!{)          // check that there is no { char before
{               // match { literally 
(?!{)           // check that there is no { char after
  (             // start capturing group
    ?<parametr> // this capturing group name is "parametr"
    .+?         // match any char (except a new line) as few times as possible
  )             // end of capturing group
}               // match } literally 

Демонстрация

Обратите внимание, что это регулярное выражение можетсопоставить недопустимые группы (строка 4 в демо), которые в реальном коде будут выбрасывать FormatException.Я надеюсь, что это не ваш случай.

Также в случае, если ваш ввод сформирован из строковой интерполяции, как

$"difficult { string.Concat(new[] { 's', 't', 'r', 'i', 'n', 'g' }) }"

Я не знаю простого способа достичь того, что вы хотите

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