简体   繁体   English

如何过滤与模式匹配的字符串列表

[英]How to filter a list of strings matching a pattern

I have a list of strings (file names actually) and I'd like to keep only those that match a filter expression like: \*_Test.txt .我有一个字符串列表(实际上是文件名),我只想保留那些与过滤器表达式匹配的字符串,例如: \*_Test.txt

What would be the best to achieve this?实现这一目标的最佳方法是什么?

Here is the answer that I came up with:这是我想出的答案:

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

You probably want to use a regular expression for this if your patterns are going to be complex....如果您的模式很复杂,您可能希望为此使用正则表达式....

you could either use a proper regular expression as your filter (eg for your specific example it would be new Regex(@"^.*_Test\.txt$") or you could apply a conversion algorithm.您可以使用适当的正则表达式作为过滤器(例如,对于您的具体示例,它将是new Regex(@"^.*_Test\.txt$")或者您可以应用转换算法。

Either way you could then just use linq to apply the regex.无论哪种方式,您都可以使用 linq 来应用正则表达式。

for example例如

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

Some people may think the above answer is incorrect, but you can use a method group instead of a lambda.有些人可能认为上面的答案不正确,但是您可以使用方法组来代替 lambda。 If you wish the full lamda you would use:如果你想要完整的 lamda,你会使用:

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

or non Linq或非 Linq

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

if you were converting the filter a simple conversion would be如果您要转换过滤器,则简单的转换将是

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

You could then also have filters like "*Test*.txt" with this method.然后,您还可以使用此方法使用"*Test*.txt"类的过滤器。

However, if you went down this conversion route you would need to make sure you escaped out all the special regular expression chars eg "."但是,如果您走这条转换路线,则需要确保您转义了所有特殊的正则表达式字符,例如“。” becomes @".", "(" becomes @"(" etc.......变成@".", "(" 变成@"(" 等等......

Edit -- The example replace is TOO simple because it doesn't convert the.编辑——示例替换太简单了,因为它不转换。 so it would find "fish_Textxtxt" so escape atleast the .所以它会找到"fish_Textxtxt" ,所以至少逃脱.

so所以

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

Have you tried LINQ:你试过LINQ:

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

or if you are running this on some old/legacy .NET version (< 3.5):或者,如果您在某些旧的/旧版 .NET 版本(< 3.5)上运行它:

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

This worked for me and is fairly simple:这对我有用,而且相当简单:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM