filtering a list using LINQ

后端 未结 5 1447
面向向阳花
面向向阳花 2020-12-09 14:38

i have a list of project objects:

IEnumerable projects

a Project class as a property called Tags

相关标签:
5条回答
  • 2020-12-09 14:56

    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());
    
    0 讨论(0)
  • 2020-12-09 15:06

    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); 
    } 
    
    0 讨论(0)
  • 2020-12-09 15:07
    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.

    0 讨论(0)
  • 2020-12-09 15:15

    EDIT: better yet, do it like that:

    var filteredProjects = 
        projects.Where(p => filteredTags.All(tag => p.Tags.Contains(tag)));
    

    EDIT2: Honestly, I don't know which one is better, so if performance is not critical, choose the one you think is more readable. If it is, you'll have to benchmark it somehow.


    Probably Intersect is the way to go:

    void Main()
    {
        var projects = new List<Project>();
        projects.Add(new Project { Name = "Project1", Tags = new int[] { 2, 5, 3, 1 } });
        projects.Add(new Project { Name = "Project2", Tags = new int[] { 1, 4, 7 } });
        projects.Add(new Project { Name = "Project3", Tags = new int[] { 1, 7, 12, 3 } });
    
        var filteredTags = new int []{ 1, 3 };
        var filteredProjects = projects.Where(p => p.Tags.Intersect(filteredTags).Count() == filteredTags.Length);  
    }
    
    
    class Project {
        public string Name;
        public int[] Tags;
    }
    

    Although that seems a little ugly at first. You may first apply Distinct to filteredTags if you aren't sure whether they are all unique in the list, otherwise the counts comparison won't work as expected.

    0 讨论(0)
  • 2020-12-09 15:18
    var result = projects.Where(p => filtedTags.All(t => p.Tags.Contains(t)));
    
    0 讨论(0)
提交回复
热议问题