Фильтровать список <T>на основе другого списка, который содержит каждый экземпляр T - PullRequest
1 голос
/ 05 декабря 2011

Итак, у меня есть коллекция объектов в одном списке, но каждый объект в этом списке содержит другой список.

Обратите внимание на следующее:

class Parent
{
    public Parent(string parentName)
    {
        this.ParentName = parentName;
    }
    public string ParentName { get; set; }
    public List<Child> Children { get; set; } 
}
class Child
{
    public Child(string name)
    {
        this.ChildName = name;
    }

    public string ChildName { get; set; }
}

По характеру приложения все родительские объекты в списке родителей являются уникальными. Несколько родителей могут содержать одного и того же ребенка, и мне нужно, чтобы родители содержали ребенка x.

Итак, допустим, что ребенок с ChildName «child1» принадлежит обоим родителям с ParentName «parent1» и «parent5». Если в коллекции 100 родителей, я хочу получить только тех, у кого есть Child с ChildName "child1"

Я бы предпочел сделать это с лямбда-выражением, но я не уверен, с чего начать, потому что у меня нет особого опыта их использования. Возможно ли это, и если да, то каков правильный подход?

Ответы [ 3 ]

3 голосов
/ 05 декабря 2011

Вы можете сделать это так:

var result = parents.Where(p => p.Children.Any(c => c.ChildName == "child1"));
3 голосов
/ 05 декабря 2011

Если класс Child определил операцию равенства путем реализации IEquatable<Child>, вы можете легко сделать это, используя лямбду, метод LINQ Enumerable.Where и метод List.Contains:

var parents = new List<Parent> { ... }; // fully populated list of parents
var child = null; // the child you are looking for goes here
var filtered = parents.Where(p => p.Children.Contains(child));

Теперь вы можете перебирать filtered и выполнять свою бизнес-логику.

Если класс Child не имеет явно определенной операции равенства (что означает, что он будет использовать правила равенства ссылок вместо проверки идентичных ChildName), то вам нужно будет включить «что проходит для равных» зайди в лямбду сам:

var filtered = parents.Where(p => p.Children.Any(c => c.ChildName == "child1"));

Примечание: Конечно, есть много других способов сделать вышеупомянутое, включая, возможно, более легкий для чтения

parents.Where(p => p.Children.Count(c => c.ChildName == "child1") > 0);

Однако это не так эффективно, как в версии Any, даже если она даст те же результаты.

В обоих случаях лямбды очень «читают как» то, что они должны делать:

  1. Я хочу, чтобы те родители, у которых в коллекции «Дети» есть этот элемент *
  2. Я хочу, чтобы те родители, у которых хотя бы один из детей имел ChildName == "child1"
2 голосов
/ 05 декабря 2011

Это сделало бы это

IEnumerable<Parent> parentsWithChild1 = parents.Where(p => p.Children.Any(c => c.ChildName == "child1"));
...