C# Linq获取指定的子级及其父级

C# Linq获取指定的子级及其父级,c#,linq,C#,Linq,我有两个班级的家长和孩子。我想让孩子符合某些标准的所有父母,例如所有父母和他们的女性孩子。我想使用Linq来完成此操作。我使用了下面的Linq查询,它返回所有有女性孩子的父母,但是孩子列表也包含男性孩子。我只想让父母和他们的女性子女在列表父母和女性子女中。请参见下面的Linq查询: List<Parent> parentsAndFemaleChildren = Parents .Where(p => p.Children.Any((c => c.Gender ==

我有两个班级的家长和孩子。我想让孩子符合某些标准的所有父母,例如所有父母和他们的女性孩子。我想使用
Linq
来完成此操作。我使用了下面的
Linq
查询,它返回所有有女性孩子的父母,但是孩子列表也包含男性孩子。我只想让父母和他们的女性子女在
列表父母和女性子女中
。请参见下面的
Linq
查询:

List<Parent> parentsAndFemaleChildren = Parents
    .Where(p => p.Children.Any((c => c.Gender == "Female")))
    .ToList();
列出父母和FemaleChildren=父母
其中(p=>p.Children.Any((c=>c.Gender==“Female”))
.ToList();
填充数据的代码如下所示

public class Parent
{
    public int ParentId {get;set;}
    public string ParentName {get;set;}
    public List<Child> Children {get;set;}
}
public class Child
{
    public int ChildId {get;set;}
    public string ChildName {get;set;}
    public string Gender {get;set;}
    public int ParentId {get;set;}
}

公共类父类
{
public int ParentId{get;set;}
公共字符串ParentName{get;set;}
公共列表子项{get;set;}
}
公营儿童
{
public int ChildId{get;set;}
公共字符串ChildName{get;set;}
公共字符串{get;set;}
public int ParentId{get;set;}
}
我已按照以下方式填充数据

public static void Main()
    {
        List<Parent> Parents = new List<Parent>();

        Parent p1 = new Parent();
        p1.ParentId = 1;
        p1.ParentName = "Parent 1";
        Parents.Add(p1);    


        Child p1C1 = new Child();
        p1C1.ChildId = 1;
        p1C1.ChildName = "Parent 1 Child 1";
        p1C1.Gender = "Male";
        p1C1.ParentId = 1;

        p1.Children = new List<Child>();

        p1.Children.Add(p1C1);

        Child p1C2 = new Child();
        p1C2.ChildId = 2;
        p1C2.ChildName = "Parent 1 Child 2";
        p1C2.Gender = "Female";
        p1C2.ParentId = 1;

        p1.Children.Add(p1C2);

        Parent p2 = new Parent();
        p2.ParentId = 2;
        p2.ParentName = "Parent 2";
        Parents.Add(p2);

        Child p2C1 = new Child();
        p2C1.ChildId = 3;
        p2C1.ChildName = "Parent 2 Child 1";
        p2C1.Gender = "Female";
        p2C1.ParentId = 2;

        p2.Children = new List<Child>();

        p2.Children.Add(p2C1);

        Child p2C2 = new Child();
        p2C2.ChildId = 4;
        p2C2.ChildName = "Parent 2 Child 2";
        p2C2.Gender = "Male";
        p2C2.ParentId = 2;

        p2.Children.Add(p2C2);

        Parent p3 = new Parent();
        p3.ParentId = 3;
        p3.ParentName = "Parent 3";
        Parents.Add(p3);

        Child p3C1 = new Child();
        p3C1.ChildId = 5;
        p3C1.ChildName = "Parent 3 Child 1";
        p3C1.Gender = "Male";
        p3C1.ParentId = 3;

        p3.Children = new List<Child>();

        p3.Children.Add(p3C1);


        DisplayFemaleChildrenAndParents(Parents);
    }

    public static void DisplayFemaleChildrenAndParents(List<Parent> Parents)
    {
        List<Parent> parentsAndFemaleChildren = Parents.Where(p => p.Children.Any((c => c.Gender == "Female"))).ToList();
        Console.WriteLine("\nShould Display Parents and their Female children details ONLY\n");
        foreach(Parent p in parentsAndFemaleChildren)
        {       
            Console.WriteLine("***********");           
            foreach(Child c in p.Children)
            {               
                Console.WriteLine(p.ParentName + " - " + c.ChildName + " - " + c.Gender);
            }
            Console.WriteLine("***********");
        }
    }
publicstaticvoidmain()
{
列表父项=新列表();
父项p1=新父项();
p1.ParentId=1;
p1.ParentName=“父1”;
添加(p1);
子p1C1=新子项();
p1C1.ChildId=1;
p1C1.ChildName=“父1子1”;
p1C1.性别=“男性”;
p1C1.ParentId=1;
p1.Children=新列表();
p1.儿童。添加(p1C1);
子p1C2=新子项();
p1C2.ChildId=2;
p1C2.ChildName=“父1子2”;
p1C2.性别=“女性”;
p1C2.ParentId=1;
p1.儿童。添加(p1C2);
父级p2=新父级();
p2.ParentId=2;
p2.ParentName=“Parent 2”;
添加(p2);
子级p2C1=新子级();
p2C1.ChildId=3;
p2C1.ChildName=“父2子1”;
p2C1.性别=“女性”;
p2C1.ParentId=2;
p2.Children=新列表();
p2.儿童。添加(p2C1);
子p2C2=新子项();
p2C2.ChildId=4;
p2C2.ChildName=“父2子2”;
p2C2.性别=“男性”;
p2C2.ParentId=2;
p2.儿童。添加(p2C2);
父项p3=新父项();
p3.ParentId=3;
p3.ParentName=“父3”;
父母。添加(p3);
子p3C1=新子项();
p3C1.ChildId=5;
p3C1.ChildName=“父3子1”;
p3C1.性别=“男性”;
p3C1.ParentId=3;
p3.儿童=新列表();
p3.儿童。添加(p3C1);
显示FemaleChildrenandParents(父母);
}
公共静态无效显示FemaleChildrenandParents(列出父项)
{
列出parentsAndFemaleChildren=Parents.Where(p=>p.Children.Any((c=>c.Gender==“Female”)).ToList();
Console.WriteLine(“\n仅显示父母及其子女的详细信息\n”);
foreach(Parents和FemaleChildren中的父p)
{       
Console.WriteLine(“*************”);
foreach(p.Children中的儿童c)
{               
Console.WriteLine(p.ParentName+“-”+c.ChildName+“-”+c.Gender);
}
Console.WriteLine(“*************”);
}
}
完整的代码可以通过dotnet fiddle查看和运行。

这将起作用:

首先获取有一些女性孩子的父母,然后过滤掉所有男性孩子,所以只显示女性

编辑:

另一种味道:

编辑2:

输出同上:

Parent 1    female children:
    Parent 1 Child 2, Gender: Female
Parent 2    female children:
    Parent 2 Child 1, Gender: Female

在最新版本的语言中,您可以使用ValueTuple:

var parentsAndFemaleChildren = Parents
    .Select(p=> (parent: p, femaleChildren: p.Children.Where(c => c.Gender == "Female").ToList()))
    .Where(p => p.femaleChildren.Any())
    .ToList();
和打印功能:

    foreach(var (p, children) in parentsAndFemaleChildren)
    {       
        Console.WriteLine("***********");           
        foreach(Child c in children)
        {               
            Console.WriteLine(p.ParentName + " - " + c.ChildName + " - " + c.Gender);
        }
        Console.WriteLine("***********");
    }

如果需要筛选只有女性子女的父母,则应使用
ALL
linq方法

确定序列的所有元素是否满足条件


我喜欢有可操作样本的问题。在Linq中,我可以说匿名类型使用得更多,所以我没有使用过,即使元组也可以使用。现在我想知道还有什么更好的…你可以用匿名类型做同样的事情。至于哪种类型的batter,我更喜欢ValueTuple,因为它们应该分配更少的资源。你认为它们在linq2sql中的行为会一样吗?实际上,我从未尝试过。但是,如果您没有在具体化结果中使用,我认为它们之间没有区别(如果基础提供程序支持元组),并且可以使用匿名类型。@learner,那么您需要创建新的
父对象
对象,该对象将只包含女性子对象。例如“.Select(p=>newparent{Id=p.Id,Name=p.Name,Children=p.Children.Where(....).ToList()})”foreach循环仅用于演示目的。我希望列出parentsAndFemaleChildren变量以包含至少有一个女性的家长,以及parentsAndFemaleChildren.Children以仅包含女性孩子,而不使用匿名类型。版本1使用foreach循环,版本2使用匿名类型。对不起,关于匿名类型,我应该说得更清楚一些,但我认为可以用以下短语来理解:我只想让父母和他们的女性子女在列表父母和女性子女中。但是我应该更清楚一些。@learner编辑了答案,包括创建一个新的父对象。
***********
Parent 1 - Parent 1 Child 1 - Male
Parent 1 - Parent 1 Child 2 - Female
***********
***********
Parent 2 - Parent 2 Child 1 - Female
Parent 2 - Parent 2 Child 2 - Male
***********
***********
Parent 3 - Parent 3 Child 1 - Male
***********

Should Display Parents and their Female children details ONLY

***********
Parent 1 - Parent 1 Child 2 - Female
***********
***********
Parent 2 - Parent 2 Child 1 - Female
***********


 ***********   v2 ***********   


Parent 1    female children:
    Parent 1 Child 2, Gender: Female
Parent 2    female children:
    Parent 2 Child 1, Gender: Female
        var parentsWithFemales = Parents.Select(p => new Parent(){ParentId = p.ParentId, ParentName = p.ParentName, Children = p.Children.Where(a => a.Gender == "Female").ToList()})
                                        // Filter out parents without female children
                                        .Where(x => x.Children.Any());
        foreach(var pc in parentsWithFemales)
        {
            Console.WriteLine(pc.ParentName + "\tfemale children:");
            foreach(var c in pc.Children)
                Console.WriteLine("\t"+c.ChildName + ", Gender: " + c.Gender);
        }
Parent 1    female children:
    Parent 1 Child 2, Gender: Female
Parent 2    female children:
    Parent 2 Child 1, Gender: Female
var parentsAndFemaleChildren = Parents
    .Select(p=> (parent: p, femaleChildren: p.Children.Where(c => c.Gender == "Female").ToList()))
    .Where(p => p.femaleChildren.Any())
    .ToList();
    foreach(var (p, children) in parentsAndFemaleChildren)
    {       
        Console.WriteLine("***********");           
        foreach(Child c in children)
        {               
            Console.WriteLine(p.ParentName + " - " + c.ChildName + " - " + c.Gender);
        }
        Console.WriteLine("***********");
    }
List<Parent> parentsAndFemaleChildren = Parents
    .Where(p => p.Children.All((c => c.Gender == "Female"))).ToList();
List<Parent> parentsAndFemaleChildren = Parents
    .Where(p => p.Children.Any((c => c.Gender == "Female")))
    .Select(s => new Parent { ParentId = s.ParentId, ParentName = s.ParentName, 
        Children = s.Children.Where(ch => ch.Gender == "Female").ToList()}).ToList();