Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to filter a list of strings matching a pattern

Tags:

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.

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(); 
like image 631
TeamWild Avatar asked Aug 10 '11 15:08

TeamWild


People also ask

How do you filter a string list in Python?

Filter a list of string using filter() method. filter() method accepts two parameters. The first parameter takes a function name or None and the second parameter takes the name of the list variable as values. filter() method stores those data from the list if it returns true, otherwise, it discards the data.

How do you know if a string matches a pattern?

To check if a String matches a Pattern one should perform the following steps: Compile a String regular expression to a Pattern, using compile(String regex) API method of Pattern. Use matcher(CharSequence input) API method of Pattern to create a Matcher that will match the given String input against this pattern.

How do I match a pattern in regex?

Most characters, including all letters ( a-z and A-Z ) and digits ( 0-9 ), match itself. For example, the regex x matches substring "x" ; z matches "z" ; and 9 matches "9" . Non-alphanumeric characters without special meaning in regex also matches itself. For example, = matches "=" ; @ matches "@" .


1 Answers

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 (e.g for your specific example it would be new Regex(@"^.*_Test\.txt$") or you could apply a conversion algorithm.

Either way you could then just use linq to apply the regex.

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. If you wish the full lamda you would use:

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

or non 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.

However, if you went down this conversion route you would need to make sure you escaped out all the special regular expression chars e.g. "." 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 .

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("*",".*"))); 
like image 86
Bob Vale Avatar answered Sep 28 '22 06:09

Bob Vale