Как фильтровать список строк, соответствующих шаблону

У меня есть список строк (фактически имена файлов), и я хотел бы сохранить только те, которые соответствуют выражению фильтра, например: \*_Test.txt.

Что было бы лучше всего для этого?

Вот ответ, который я придумал:

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();

Ответ 1

Возможно, вы захотите использовать регулярное выражение для этого, если ваши шаблоны будут сложными....

вы можете использовать правильное регулярное выражение как ваш фильтр (например, для вашего конкретного примера это будет new Regex(@"^.*_Test\.txt$"), или вы можете применить алгоритм преобразования.

В любом случае вы можете просто использовать linq для применения регулярного выражения.

например

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

Некоторые люди могут подумать, что приведенный выше ответ неверен, но вы можете использовать группу методов вместо лямбда. Если вы хотите использовать полную ламу, вы будете использовать:

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

или не Linq

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

если вы конвертировали фильтр, простым преобразованием было бы

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

У вас также могут быть такие фильтры, как "*Test*.txt" с помощью этого метода.

Однако, если вы спустили этот маршрут преобразования, вам нужно будет убедиться, что вы выбрали все специальные символы регулярных выражений, например. "становится @". "," ( "становится @" (" etc.......

Изменить. Пример замены TOO просто, потому что он не преобразует. поэтому он найдет "fish_Textxtxt", так что избегайте, по крайней мере, .

так

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

Ответ 2

Вы пробовали LINQ:

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

или если вы используете это в старой/старой версии .NET(< 3.5):

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

Ответ 3

Это сработало для меня и довольно просто:

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