I need to remove items from the list that match a collection of string patterns. If needed, I can loop through the list/array of patterns to remove rather than matching all of them at once.
Note: the string patterns are dynamic and we don’t know what will be passed in.
We do know the patterns can have Asterisk and/or Question Marks, and have the same function as in:
System.IO.Directory.GetFiles(, );
Where ?xyz.txt
would find 1xyz.txt
, 2xyz.txt
, but not 12xyz.txt
and not xyz.txt
This is what I came up with which does not work.
string exclude = "*yf*";
List<string> listRemaining = listAll.Where(x => !listAll.Contains(exclude)).ToList();
This is an example of patterns for items to remove from the list:
*yf*
*xName.txt
?MyFileName*
And this is a sample list of strings where we need to remove items matching the 3 patterns above:
AyFileName.log
AyFilexName.txt
ByFilexName.log
ByFileName.txt
zMyFileName.log
zMyFileName.txt
SomeFancyFileName.log
SomeFancyFileName.txt
TodayFileName.log
TodayFileName.txt
UglyFileName.log
UglyFileName.txt
Items to be removed?
Pattern to remove: *yf*
will remove:
`SomeFancyFileName.log`
`SomeFancyFileName.txt`
`UglyFileName.log`
`UglyFileName.txt`
Pattern to remove: *xName.txt
will remove:
AyFilexName.txt
Pattern to remove: ?MyFileName*
will remove:
zMyFileName.log
zMyFileName.txt
Thank you.
CodePudding user response:
The best solution would be the File globbing as @jwdonahue mentioned.
https://docs.microsoft.com/en-us/dotnet/core/extensions/file-globbing
But if you want to build your own solution for that, this might be a start.
public static IEnumerable<string> Filter(string pattern, IEnumerable<string> list) {
return list.Where(e =>!Match(pattern, e));
}
public static bool Match(string pattern, string input) {
var modifiedPattern = pattern
.Replace(@"\", @"\\")
.Replace(".", @"\.")
.Replace("*", ".*")
.Replace("?", ".");
modifiedPattern = "^" modifiedPattern "$";
return Regex.IsMatch(input, modifiedPattern, RegexOptions.IgnoreCase);
}
Which you can call like
var filterPattern = "?MyFileName*";
var listRemaining = Filter(filterPattern, listAll).ToList();