J'ai une liste de chaînes (noms de fichiers en fait) et je voudrais garder uniquement celles qui correspondent à une expression de filtre comme: \*_Test.txt
.
Quel serait le meilleur pour y parvenir?
Voici la réponse que j'ai trouvée:
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();
Vous voudrez probablement utiliser une expression régulière pour cela si vos modèles vont être complexes ....
vous pouvez soit utiliser une expression régulière appropriée comme filtre (par exemple, pour votre exemple spécifique, ce serait new Regex(@"^.*_Test\.txt$")
ou vous pouvez appliquer un algorithme de conversion.
Dans les deux cas, vous pouvez simplement utiliser linq pour appliquer l'expression régulière.
par exemple
var myRegex=new Regex(@"^.*_Test\.txt$");
List<string> resultList=files.Where(myRegex.IsMatch).ToList();
Certaines personnes peuvent penser que la réponse ci-dessus est incorrecte, mais vous pouvez utiliser un groupe de méthodes au lieu d'un lambda. Si vous souhaitez la lamda complète, vous utiliserez:
var myRegex=new Regex(@"^.*_Test\.txt$");
List<string> resultList=files.Where(f => myRegex.IsMatch(f)).ToList();
ou non Linq
List<string> resultList=files.FindAll(delegate(string s) { return myRegex.IsMatch(s);});
si vous convertissiez le filtre, une simple conversion serait
var myFilter="*_Test.txt";
var myRegex=new Regex("^" + myFilter.Replace("*",".*") +"$");
Vous pouvez alors également avoir des filtres comme "*Test*.txt"
avec cette méthode.
Cependant, si vous descendiez cette route de conversion, vous devez vous assurer d'avoir échappé à tous les caractères d'expressions régulières spéciales, par exemple "." devient @ ".", "(" devient @ "(" etc .......
Modifier - L'exemple de remplacement est TROP simple car il ne convertit pas le. il trouverait donc "fish_Textxtxt"
alors échappez au moins au .
alors
string myFilter="*_Test.txt";
foreach(char x in @"\+?|{[()^$.#") {
myFilter = myFilter.Replace(x.ToString(),@"\"+x.ToString());
}
Regex myRegex=new Regex(string.Format("^{0}$",myFilter.Replace("*",".*")));
Avez-vous essayé LINQ:
List<string> resultList = files.Where(x => x.EndsWith("_Test.txt")).ToList();
ou si vous l'exécutez sur une ancienne version .NET (<3.5):
List<string> resultList = files.FindAll(delegate(string s) {
return s.EndsWith("_Test.txt");
});
Cela a fonctionné pour moi et est assez simple:
List<string> keys = new List<string>();
//populate your list
var myregex = new Regex("^.+$");
List<string> matchlist = keys.Where(i=>myregex.IsMatch(i)).ToList();