2010-05-26 13 views
10

En el ejemplo simplificado, hay 2 expresiones regulares, una mayúscula y la otra no. La idea sería eficientemente crear una colección IEnumerable (ver "combinados" a continuación) que combina los resultados.Combina eficientemente MatchCollections en .Net Regex

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 

} 

En la práctica, los MatchCollections puede contener miles de resultados y se pasan con frecuencia el uso de expresiones regulares larga creados de forma dinámica, por lo que me gustaría a alejarse de la copia de los resultados a las matrices, etc. Todavía estoy aprendiendo y LINQ Estoy confundido sobre cómo combinar esto o lo que el rendimiento alcanza a un proceso que ya es lento.

Respuesta

17

Hay tres pasos aquí:

  1. convertir el MatchCollection 's de IEnumerable<Match>' s
  2. Concatenar las secuencias
  3. Filtrar por si la propiedad Match.Success es cierto Código

:

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

Al hacerlo, crea un nuevo enumerador que solo ejecuta cada paso a medida que se obtiene el siguiente resultado, por lo que solo termina enumerando a través de cada colección una vez, total. Por ejemplo, Concat() solo comenzará a ejecutar el segundo enumerador después de que se agote el primer enumerador.

+3

Creo que .Concat() podría ser mejor que .Union() aquí, a menos que intencionalmente quiera evitar la superposición en los resultados. – jmnben

Cuestiones relacionadas