LINQ - 过滤集合中的子集合

6

假设我有以下类:

class Parent
{
    bool Gender { get; set; }
    List<Child> Children { get; set; }
}


class Child
{
    bool Gender { get; set; }
    List<Child> GrandChildren { get; set; }
}


class GrandChild
{
    bool Gender { get; set; }
}

使用linq,有人能帮我通过返回一个List<Child>来筛选父对象,其中每个Child都有Gender == false,且每个Child的GrandChild都有Gender == false吗?
我已经成功返回了一个List<GrandChild>,但我真的需要维护层次结构。

2
你的意思是你只想返回那些孩子性别为假且所有孩子的性别都为假的家长吗? - Jon Skeet
1
顺便提一下,我建议您将“Gender”属性更改为枚举{男性,女性},因为“Gender=true/false”不太清楚易懂... - digEmAll
3
我喜欢性别是布尔值。男性用“true”表示,女性用“false”表示?就像现实生活中一样?;-P - Klaus Byskov Pedersen
性别只是一个例子.. 感谢所有快速的回答。 - pedrodbsa
也许我没有表达清楚... 这些查询并没有过滤孙子节点... 它们只返回一个列表<Child>,其中包含Gender == false的GrandChild对象。但是GrandChildren集合仍然没有被过滤... 它仍然返回Gender == false和true的GranChild。 - pedrodbsa
4个回答

17
你正在寻找。
.Where(p => p.Children.All(c => !c.Gender && c.GrandChildren.All(g => !g.Gender))

我想过滤掉所有Gender == true的对象,但仍保持相同的结构。 - pedrodbsa
@teknoplast:你是什么意思? - SLaks
我想过滤List<Child>和List<Grandchildren>,使Gender == false。使用您的代码,它返回一个经过过滤的List<Child>,但是GrandChildren没有被过滤。 - pedrodbsa
您需要克隆您的Child对象,然后在克隆列表上调用RemoveAll以摆脱不需要的孙子对象。 - SLaks
1
那么为什么这个被接受的答案不是我的,而我的确实做到了这一点呢? :) - fejesjoco

7

您的问题有点模糊。这里提供一种解决方案,重建子代和孙代列表。我不确定是否需要child.GrandChildren.All(gc =>!gc.Gender),所以为了清晰起见,我将其省略:

parents.Select(parent => new Parent
{
  Gender = parent.Gender,
  Children = parent.Children.Where(child => !child.Gender).Select(child => new Child
    {
      Gender = false,
      GrandChildren = child.GrandChildren.Where(gc => !gc.Gender).ToList()
    }
  ).ToList()
})

3
  • 帮我过滤一个父对象
  • 通过返回一个List<Child>
  • 其中每个Child的Gender == false
  • 并且每个Child的GrandChild的Gender == false?
List<Child> results =
(
  from c in theParent.Children
  where !c.Gender
  where c.GrandChildren.Any(gc => !gc.Gender)
  select c
).ToList()

根据您的评论,您真正想要的是:
List<Parent> result = 
(
from p in Parents
where !p.Gender
select new Parent()
{
  Gender = p.Gender,
  Children = 
  (
    from c in p.Children
    where !c.Gender
    select new Child()
    {
      Gender = c.Gender,
      GrandChildren =
      (
        from gc in c.GrandChildren
        where !gc.Gender
        select new GrandChild()
        {
          Gender = gc.Gender
        }
      ).ToList()
    }
  ).ToList()
}).ToList();

1
var filteredParents = 
    from p in parents
    where p.Children.All(child => !child.Gender &&
                         child.GrandChildren.All(grandChild => !grandChild.Gender))
    select p;

在这里使用All方法可以确保传递给该方法的谓词对给定序列中的所有元素都为真。
给定代码检查每个具有All子项的父项,其中子项 (Gender = false) 并且还有All孙项Gender = false

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接