Как я могу получить совпадение с регулярным выражением, которое будет добавлено только один раз в коллекцию совпадений? - PullRequest
14 голосов
/ 20 марта 2009

У меня есть строка с несколькими html-комментариями. Мне нужно посчитать уникальные совпадения выражения.

Например, строка может быть:

var teststring = "<!--X1-->Hi<!--X1-->there<!--X2-->";

В настоящее время я использую это, чтобы получить совпадения:

var regex = new Regex("<!--X.-->");
var matches = regex.Matches(teststring);

Результатов этого 3 матча. Тем не менее, я хотел бы, чтобы это было только 2 совпадения, так как есть только два уникальных совпадения.

Я знаю, что, возможно, смогу перебрать полученную MatchCollection и удалить лишнюю Match, но я надеюсь, что есть более элегантное решение.

Уточнение : Пример строки значительно упрощен по сравнению с тем, что на самом деле используется. Это может быть X8 или X9, и в строке, вероятно, есть десятки каждого.

Ответы [ 5 ]

24 голосов
/ 20 марта 2009

Я бы просто использовал Enumerable.Distinct Method , например, вот так:

string subjectString = "<!--X1-->Hi<!--X1-->there<!--X2--><!--X1-->Hi<!--X1-->there<!--X2-->";
var regex = new Regex(@"<!--X\d-->");
var matches = regex.Matches(subjectString);
var uniqueMatches = matches
    .OfType<Match>()
    .Select(m => m.Value)
    .Distinct();

uniqueMatches.ToList().ForEach(Console.WriteLine);

Выводит это:

<!--X1-->  
<!--X2-->

Для регулярного выражения, вы могли бы использовать это?

(<!--X\d-->)(?!.*\1.*)

Кажется, что работает с вашей тестовой строкой в ​​RegexBuddy, по крайней мере =)

// (<!--X\d-->)(?!.*\1.*)
// 
// Options: dot matches newline
// 
// Match the regular expression below and capture its match into backreference number 1 «(<!--X\d-->)»
//    Match the characters “<!--X” literally «<!--X»
//    Match a single digit 0..9 «\d»
//    Match the characters “-->” literally «-->»
// Assert that it is impossible to match the regex below starting at this position (negative lookahead) «(?!.*\1.*)»
//    Match any single character «.*»
//       Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
//    Match the same text as most recently matched by capturing group number 1 «\1»
//    Match any single character «.*»
//       Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
2 голосов
/ 20 марта 2009

Похоже, вы делаете две разные вещи:

  1. Соответствующие комментарии, такие как / <- X. -> /
  2. Нахождение множества уникальных комментариев

Так что вполне логично обрабатывать их как два разных шага:

var regex = new Regex("<!--X.-->");
var matches = regex.Matches(teststring);

var uniqueMatches = matches.Cast<Match>().Distinct(new MatchComparer());

class MatchComparer : IEqualityComparer<Match>
{
    public bool Equals(Match a, Match b)
    {
        return a.Value == b.Value;
    }

    public int GetHashCode(Match match)
    {
        return match.Value.GetHashCode();
    }
}
0 голосов
/ 20 марта 2009

В зависимости от того, сколько у вас есть Xn, вы можете использовать:

(\<!--X1--\>){1}.*(\<!--X2--\>){1}

Это будет соответствовать каждому вхождению X1, X2 и т. Д. Только при условии, что они в порядке.

0 голосов
/ 20 марта 2009

Захват внутренней части комментария в виде группы. Затем поместите эти строки в хеш-таблицу (словарь). Затем попросите словарь подсчитать его количество, так как он будет самостоятельно отсеивать повторы.

var teststring = "<!--X1-->Hi<!--X1-->there<!--X2-->";
var tokens = new Dicationary<string, string>();
Regex.Replace(teststring, @"<!--(.*)-->",   
     match => {  
     tokens[match.Groups[1].Value] = match.Groups[1].Valuel;  
     return ""; 
     });
var uniques = tokens.Keys.Count;

Используя конструкцию Regex.Replace, вы получаете вызов лямбды при каждом совпадении. Поскольку вы не заинтересованы в замене, вы не устанавливаете ее равной чему-либо.

Вы должны использовать Group [1], потому что group [0] - это полное совпадение. Я повторяю только одно и то же с обеих сторон, чтобы его было легче поместить в словарь, в котором хранятся только уникальные ключи.

0 голосов
/ 20 марта 2009

Извлеките комментарии и сохраните их в массиве. Затем вы можете отфильтровать уникальные значения.

Но я не знаю, как реализовать это в C #.

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