2011-08-10 17 views
11

Tengo una lista de cadenas (nombres de archivo en realidad) y me gustaría conservar solo aquellas que coincidan con una expresión de filtro como: \*_Test.txt.Cómo filtrar una lista de cadenas que coincidan con un patrón

¿Cuál sería la mejor manera de lograrlo?

Aquí está la respuesta que se me ocurrió:

List<string> files = new List<string>(); 
files.Add("MyFile1.csv"); 
files.Add("MyFile1_Test.txt"); 
files.Add("MyFile2.csv"); 
files.Add("MyFile2_Test.txt"); 
files.Add("MyFile3.csv"); 
files.Add("MyFile3_Test.txt"); 
files.Add("MyFile_Testtxttxt.txt"); 

// Define a filter 
string filter = "*_Test.txt"; 

// Make the filter regex safe 
foreach (char x in @"\+?|{[()^$.#") 
    filter = filter.Replace(x.ToString(), @"\" + x.ToString()); 

filter = string.Format("^{0}$",filter.Replace("*", ".*")); 

// Old School 
List<string> resultList1 = files.FindAll(delegate(string s) { return Regex.IsMatch(s, filter, RegexOptions.IgnoreCase); }); 

// Version using LINQ 
List<string> resultList2 = files.Where(x => Regex.IsMatch(x, filter, RegexOptions.IgnoreCase) == true).ToList(); 
+0

me gustaría que el filtro para ser flexible para que pudiera usar \ * \ * o \ * .t \ * o cualquier cantidad de combinaciones . Eliminar el \ * no me daría las coincidencias parciales. – TeamWild

+0

Eeep, una corrección a mi respuesta necesita cambiar la cadena. Formatear a '("^{0} $ ")' de lo contrario, encontrará '" fish_Test.txtWIBBLE "' –

Respuesta

18

Probablemente quieras Para usar una expresión regular para esto, si sus patrones van a ser complejos ...

puede usar una expresión regular adecuada como su filtro (por ejemplo, para su ejemplo específico sería new Regex(@"^.*_Test\.txt$") o podría aplicar un algoritmo de conversión.

De cualquier forma, puede utilizar linq para aplicar la expresión regular.

por ejemplo

var myRegex=new Regex(@"^.*_Test\.txt$"); 
List<string> resultList=files.Where(myRegex.IsMatch).ToList(); 

Algunas personas pueden pensar que la respuesta anterior es correcta, pero se puede utilizar un método de grupo en lugar de un lambda. Si se desea que el lambda completo que usaría:

var myRegex=new Regex(@"^.*_Test\.txt$"); 
List<string> resultList=files.Where(f => myRegex.IsMatch(f)).ToList(); 

o no LINQ

List<string> resultList=files.FindAll(delegate(string s) { return myRegex.IsMatch(s);}); 

si estuviera convirtiendo el filtro de una simple conversión habría

var myFilter="*_Test.txt"; 
var myRegex=new Regex("^" + myFilter.Replace("*",".*") +"$"); 

A continuación, podría también tener filtros como "*Test*.txt" con este método.

Sin embargo, si realizó esta ruta de conversión, deberá asegurarse de haber escapado de todos los caracteres especiales de expresión regular, p. "." se convierte en @ ".", "(" se convierte en @ "(" etc .......

Editar - El ejemplo de reemplazar es DEMASIADO simple porque no convierte el. por lo que encontraría "fish_Textxtxt" para escapar al menos el .

por lo

string myFilter="*_Test.txt"; 
foreach(char x in @"\+?|{[()^$.#") { 
    myFilter = myFilter.Replace(x.ToString(),@"\"+x.ToString()); 
} 
Regex myRegex=new Regex(string.Format("^{0}$",myFilter.Replace("*",".*"))); 
7

Ha intentado LINQ:

List<string> resultList = files.Where(x => x.EndsWith("_Test.txt")).ToList(); 

o si está ejecutando esto en alguna versión antigua/legado .NET (< 3.5):

List<string> resultList = files.FindAll(delegate(string s) { 
    return s.EndsWith("_Test.txt"); 
}); 
+0

Y puede agregar expresiones regulares a eso, si quiere algo más flexible, pero tal vez complicado. http://msdn.microsoft.com/en-us/library/ms228595% 28v = VS.100% 29.aspx – Johnny5

+0

Tenía la esperanza de que hubiera una manera rápida sin utilizar expresiones regulares, ya que eso siempre termina en un dolor de cabeza. Puedo usar LINQ así que lo intentaré y veré qué sucede. – TeamWild

1

Esto funcionó para mí y es bastante simple:.

List<string> keys = new List<string>(); 
//populate your list 
var myregex = new Regex("^.+$"); 
List<string> matchlist = keys.Where(i=>myregex.IsMatch(i)).ToList(); 
Cuestiones relacionadas