i have a list of project objects:
IEnumerable<Project> projects
a Project class as a property called Tags. this is a int[]
i have a variable called filteredTags which is also a int[].
So lets say my filtered tags variable looks like this:
int[] filteredTags = new int[]{1, 3};
I want to filter my list (projects) to only return projects that have ALL of the tags listed in the filter (in this case at least tag 1 AND tag 3 in the Tags property).
I was trying to use Where() and Contains() but that only seems to work if i am comparing against a single value. How would i do this to compare a list against another list where i need a match on all the items in the filtered list ??
This question is related to
c#
linq
collections
tags
ienumerable
Based on http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b,
EqualAll is the approach that best meets your needs.
public void Linq96()
{
var wordsA = new string[] { "cherry", "apple", "blueberry" };
var wordsB = new string[] { "cherry", "apple", "blueberry" };
bool match = wordsA.SequenceEqual(wordsB);
Console.WriteLine("The sequences match: {0}", match);
}
var filtered = projects;
foreach (var tag in filteredTags) {
filtered = filtered.Where(p => p.Tags.Contains(tag))
}
The nice thing with this approach is that you can refine search results incrementally.
We should have the projects which include (at least) all the filtered tags, or said in a different way, exclude the ones which doesn't include all those filtered tags.
So we can use Linq Except
to get those tags which are not included. Then we can use Count() == 0
to have only those which excluded no tags:
var res = projects.Where(p => filteredTags.Except(p.Tags).Count() == 0);
Or we can make it slightly faster with by replacing Count() == 0
with !Any()
:
var res = projects.Where(p => !filteredTags.Except(p.Tags).Any());
var result = projects.Where(p => filtedTags.All(t => p.Tags.Contains(t)));
Source: Stackoverflow.com