Reputation: 3845
Im quite new to C# so trying to test a simple string filter but not getting the desired results. This is my test method:
[TestMethod]
public void Test_ExceptFilter()
{
IEnumerable<string> allnames = new List<string>(){"Thumbs.db","~","one","two exe here","three"};
var u = FileLister.GetFilteredList(allnames, new [] { "thumbs","~"}, false);
}
I have a static class called FileLister which has the GetFilteredList method, and the bit that is not working is when i try to return a list that DOES NOT CONTAIN any strings that are in the second IEnumerable.
So in my example here, i expect var u to have "one","two exe here" and "three" only, but it has all the items from the allnames list!.
These are the various ways i have tried and in all of them, the part im struggling with is where the boolean includewords is passed in as false:
//Return strings that contain or dont contain any element in the array
public static IEnumerable<string> GetFilteredList(IEnumerable<string> myfiles,
IEnumerable<string> filterbythesewords, bool includewords)
{
if (includewords)
{
return from line in myfiles
where filterbythesewords.Any(item => line.Contains(item))
select line;
}
else
{
return from line in myfiles
where filterbythesewords.Any(item => !line.Contains(item))
select line;
}
}
SECOND TRIAL
//Return strings that contain or dont contain any element in the array
public static IEnumerable<string> GetFilteredList(IEnumerable<string> myfiles,
IEnumerable<string> filterbythesewords, bool includewords)
{
if (includewords)
{
return from line in myfiles
where filterbythesewords.Any(item => line.Contains(item))
select line;
}
else
{
List<string> p = new List<string>();
p.AddRange(myfiles.Except(filterbythesewords));
return p;
}
}
THIRD TRIAL
//Return strings that contain or dont contain any element in the array
public static IEnumerable<string> GetFilteredList(IEnumerable<string> myfiles,
IEnumerable<string> filterbythesewords, bool includewords)
{
if (includewords)
{
return from line in myfiles
where filterbythesewords.Any(item => line.Contains(item))
select line;
}
else
{
return myfiles.Where(file => filterbythesewords.Any(x => !file.ToUpperInvariant().Contains(x.ToUpperInvariant())));
}
}
How can i make this work please? Ultimately i want to be able to filter filenames from a directory listing based on their file extensions or part of their names.
cheers
Upvotes: 2
Views: 393
Reputation: 1500535
The problem is that you're using Any
with a negative condition - which means you'll include the value if there are any words that aren't included in the candidate. Instead, you want to think of it as:
So you could use:
return myfiles.Where(file => filterbythesewords.All(item => !file.Contains(item));
or
return myfiles.Where(file => !filterbythesewords.Any(item => file.Contains(item));
(There's no need for a query expression here - when you're basically just doing a simple filter, query expressions don't help readability.)
Upvotes: 10