Эффективно объединить MatchCollections в .Net Regex - PullRequest
11 голосов
/ 27 мая 2010

В упрощенном примере есть 2 регулярных выражения, одно с учетом регистра, другое нет. Идея состояла бы в том, чтобы эффективно создать коллекцию IEnumerable (см. «Комбинированную» ниже), объединяющую результаты.

string test = "abcABC";
string regex = "(?<grpa>a)|(?<grpb>b)|(?<grpc>c)]";
Regex regNoCase = new Regex(regex, RegexOptions.IgnoreCase);
Regex regCase = new Regex(regex);

MatchCollection matchNoCase = regNoCase.Matches(test);
MatchCollection matchCase = regCase.Matches(test);

//Combine matchNoCase and matchCase into an IEnumerable
IEnumerable<Match> combined= null;
foreach (Match match in combined)
{
    //Use the Index and (successful) Groups properties 
    //of the match in another operation

}

На практике MatchCollections может содержать тысячи результатов и часто запускаться с использованием длинных динамически создаваемых REGEX-ов, поэтому я бы хотел не копировать результаты в массивы и т. Д. Я все еще изучаю LINQ и не совсем понимаю, как чтобы объединить их или то, что скажется на производительности и без того медлительном процессе.

Ответы [ 2 ]

18 голосов
/ 27 мая 2010

Здесь три шага:

  1. Преобразование MatchCollection в IEnumerable<Match> '
  2. Объединить последовательности
  3. Фильтр по истинному свойству Match.Success

Код:

IEnumerable<Match> combined = matchNoCase.OfType<Match>().Concat(matchCase.OfType<Match>()).Where(m => m.Success);

В результате этого создается новый перечислитель, который выполняет каждый шаг только при получении следующего результата, так что вы в конечном итоге перечисляете все коллекции только один раз. Например, Concat () начнет выполнение второго перечислителя только после того, как закончится первый.

0 голосов
/ 27 июня 2018

Ответ, помеченный как правильный, создает IEnumerable с двумя совпадениями. Правильный способ объединения приведен ниже:

var combined = matches.Where(e=>e.Success).Select(e=>e.Value);
...