如何筛选与模式匹配的字符串列表

时间:2011-08-10 15:29:26

标签: c# pattern-matching

我有一个字符串列表(实际上是文件名),我只想保留那些匹配过滤器表达式的字符串: \*_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();

3 个答案:

答案 0 :(得分:29)

如果您的模式变得复杂,您可能希望使用正则表达式....

您可以使用正确的正则表达式作为过滤器(例如,您的具体示例为new Regex(@"^.*_Test\.txt$"),或者您可以应用转换算法。

无论哪种方式,您都可以使用linq来应用正则表达式。

例如

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

有些人可能认为上述答案不正确,但您可以使用方法组而不是lambda。如果您希望使用完整的lamda:

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"等过滤器。

但是,如果你沿着这条转化路线走下去,你需要确保你逃脱了所有特殊的正则表达式字符,例如: “”成为@“。”,“(”成为@“(”等.......

编辑 - 示例替换是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("*",".*")));

答案 1 :(得分:8)

你试过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"); 
});

答案 2 :(得分:1)

这对我有用,而且相当简单:

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