使用LINQ过滤列表

时间:2011-02-23 11:58:00

标签: c# linq collections tags ienumerable

我有一个项目对象列表:

IEnumerable<Project> projects

项目类作为名为标记的属性。这是 int []

我有一个名为 filteredTags 的变量,它也是 int []

所以我想说我的过滤标签变量如下所示:

 int[] filteredTags = new int[]{1, 3};

我想过滤我的列表(项目),只返回包含过滤器中列出的所有标记的项目(在这种情况下,至少标记1和标记中的标记3 属性)。

我尝试使用 Where ()和包含(),但只有在我与单个值进行比较时才会起作用。我如何将列表与另一个列表进行比较,我需要对过滤列表中的所有项目进行匹配?

6 个答案:

答案 0 :(得分:39)

编辑:更好的是,这样做:

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

EDIT2:老实说,我不知道哪一个更好,所以如果表现不重要,请选择你认为更具可读性的那个。如果是,你将不得不以某种方式对它进行基准测试。


可能Intersect是要走的路:

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;
}

虽然起初看起来有点难看。如果您不确定它们在列表中是否都是唯一的,则可以先将Distinct应用于filteredTags,否则计数比较将无法按预期工作。

答案 1 :(得分:3)

我们应该让项目包括(至少)所有过滤的标签,或以不同的方式说明,排除不包括所有过滤标签的项目。 因此,我们可以使用Linq Except来获取未包含的标记。然后我们可以使用Count() == 0只包含那些不包含标签的内容:

var res = projects.Where(p => filteredTags.Except(p.Tags).Count() == 0);

或者我们可以通过将Count() == 0替换为!Any()

来加快速度
var res = projects.Where(p => !filteredTags.Except(p.Tags).Any());

答案 2 :(得分:2)

var result = projects.Where(p => filtedTags.All(t => p.Tags.Contains(t)));

答案 3 :(得分:1)

var filtered = projects;
foreach (var tag in filteredTags) {
  filtered = filtered.Where(p => p.Tags.Contains(tag))
}

这种方法的好处在于您可以逐步优化搜索结果。

答案 4 :(得分:0)

基于http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

EqualAll是最能满足您需求的方法。

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); 
} 

答案 5 :(得分:-1)

试试这个:

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