Linq Get Specified Children и их родители - PullRequest
4 голосов
/ 07 мая 2020

У меня два класса Parent и Child. Я хотел бы получить всех родителей, чьи дети соответствуют определенным критериям, например, всех родителей и их детей женского пола. Я хотел бы сделать это с помощью Linq. Я использовал следующий запрос Linq, и он возвращает всех родителей с детьми женского пола, однако список детей также содержит детей мужского пола. Я хотел бы иметь родителей и их детей женского пола только в List<Parent> parentsAndFemaleChildren. См. Запрос Linq ниже:

List<Parent> parentsAndFemaleChildren = Parents
    .Where(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 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("***********");
        }
    }

Полный код можно увидеть и запустить через do tnet fiddle щелкните здесь .

Ответы [ 3 ]

2 голосов
/ 07 мая 2020

В последней версии языка вы можете играть со значениями:

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("***********");
    }
2 голосов
/ 07 мая 2020

Это будет работать: https://dotnetfiddle.net/ckwCs1

    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.Where(c=>c.Gender == "Female"))
            {               
                Console.WriteLine(p.ParentName + " - " + c.ChildName + " - " + c.Gender);
            }
            Console.WriteLine("***********");
        }
    }
***********
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
***********

Сначала вы выбираете родителей, у которых вообще есть дети женского пола, а затем отфильтровываете всех детей мужского пола, поэтому отображаются только женщины.

EDIT:

Другой вариант:

https://dotnetfiddle.net/sFObju

    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.Where(c=>c.Gender == "Female"))
            {               
                Console.WriteLine(p.ParentName + " - " + c.ChildName + " - " + c.Gender);
            }
            Console.WriteLine("***********");
        }

                    Console.WriteLine("\n\n ***********   v2 ***********   \n\n");


        // alternative
        var parentsWithFemales = Parents.Select(p => new {p, FemaleChildren = p.Children.Where(a => a.Gender == "Female")})
                                        // Filter out parents without female children
                                        .Where(x => x.FemaleChildren.Any());
        foreach(var pc in parentsWithFemales)
        {
            Console.WriteLine(pc.p.ParentName + "\tfemale children:");
            foreach(var c in pc.FemaleChildren)
                Console.WriteLine("\t"+c.ChildName + ", Gender: " + c.Gender);
        }

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

Edit2 :

https://dotnetfiddle.net/N8K0AF

        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
1 голос
/ 07 мая 2020

Если вам нужно отфильтровать родителей, у которых есть ТОЛЬКО дети женского пола, вы должны использовать метод ALL linq.

MSDN говорит о методе .All:

Определяет, все ли элементы последовательности удовлетворяют условию.

List<Parent> parentsAndFemaleChildren = Parents
    .Where(p => p.Children.All((c => c.Gender == "Female"))).ToList();

Если вы хотите получить родителей, у которых есть хотя бы один ребенок женского пола, и выберите только детей женского пола, тогда вы можно использовать метод select с Where:

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...