Home > Software engineering >  Using C# 4.8: Most efficient way to remove items matching string patterns from a string array or str
Using C# 4.8: Most efficient way to remove items matching string patterns from a string array or str

Time:05-01

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