2010-06-03 3 views
1

나는 2 개의 목록이 있습니다.더 나은 Linq 필터링에 대한 쿼리 자녀가없는 부모 목록

var adultList = new List<Dude>(); 
adultList.Add(new Dude() { ID = 2, Name = "Randy Marsh" }); 
adultList.Add(new Dude() { ID = 3, Name = "Jimbo Kern" }); // no kids 
adultList.Add(new Dude() { ID = 4, Name = "Gerald Broflovski" }); 
adultList.Add(new Dude() { ID = 5, Name = "Stuart McCormick" }); 
adultList.Add(new Dude() { ID = 6, Name = "Liane Cartman" }); 
adultList.Add(new Dude() { ID = 7, Name = "Ned Gerblansky" }); // no kids 

var childList = new List<Dude>(); 
childList.Add(new Dude() { ID = 8, Name = "Stan Marsh", ParentID = 2 }); 
childList.Add(new Dude() { ID = 9, Name = "Kyle Broflovski", ParentID = 4 }); 
childList.Add(new Dude() { ID = 10, Name = "Ike Broflovski", ParentID = 4 }); 
childList.Add(new Dude() { ID = 11, Name = "Kenny McCormick", ParentID = 5 }); 
childList.Add(new Dude() { ID = 12, Name = "Eric Cartman", ParentID = 6 }); 

모든 애들이없는 adultList의 Dudes를 반환하는 Linq 쿼리를 반환하고 싶습니다. 결과 목록에도 null 항목이 없어야합니다 (위의 예제에서 Count()가 2이고 Jimbo와 Ned 만 반환해야 함).

var nullList = new List<Dude>(); 
nullList.Add(null); 
var adultsWithNoChildren = adultList.GroupJoin(
    childList, 
    p => p.ID, 
    c => c.ParentID, 
    (p, c) => 
    { 
    if (c.FirstOrDefault() == null) return p; 
    return null; 
    }) 
    .Except(nullList); 

이렇게하는 것이 가장 좋은 방법입니까? 거기에 다른 Linq 함수 또는 다른 뭔가가 있습니까? nullList가 생성된다는 아이디어가 마음에 들지 않지만 결과 목록에 정확한 개수가 있는지 확인하는 것만 큼.

감사

답변

5

내 접근 방식은 다음과 같이 될 것이다 : 약

var adultNoChildren = (from adult in adultList 
        where !childList.Any(child => child.ParentID == adult.ID) 
        select adult).ToList(); 

이것은 또한 다른 LINQ 구문을 사용하여 수행 할 수 있습니다,하지만 난 기억 할 수 없다 : (좋은 점 결과를 찾자 마자 바로 그만두므로 어린이가없는 어른들 만 전체 아동 목록을 통과하게됩니다.)

+0

모든 응답에 감사드립니다 (Anthony, Jake, LukeH). 이는 Any를 사용하기 때문에 최상 (ToList 제외)입니다. 이는 성능 향상에 도움이됩니다. – Andre

1
adultList.Where(x => !childList.Select(y => y.ParentID).Contains(x.ID)); 
1
var noKids = from adult in adultList 
       join child in childList 
       on adult.ID equals child.ParentID into g 
       from item in g.DefaultIfEmpty() 
       where item == null 
       select adult; 
1
목록이 전혀 크기가있는 경우
var noKids = adultList.Where(a => !childList.Any(c => c.ParentID == a.ID)); 
+0

기본적으로 마이클 스텀 (Michael Stum)이 쿼리 독해 구문에서 유창한 확장 메서드 구문에 이르는 해답을 번역 한 것입니다. – LukeH

2

, 나는 GroupJoin를 포함하는 솔루션을 권장해야 n 개의 +의 m, 대 곳에! 어떤 비용 n 개의 * 분에게 비용 hashjoin로 인해

IEnumerable<Dude> noKids = 
    from adult in adultList 
    join child in childList 
    on adult.ID equals child.ParentID into kids 
    where !kids.Any() 
    select adult; 

또는 방법 양식

에서
IEnumerable<Dude> noKids = adultList.GroupJoin(
    childList, 
    adult => adult.ID, 
    child => child.ParentID, 
    (adult, kids) => new {Dude = adult, AnyKids = kids.Any() }) 
    .Where(x => !x.AnyKids) 
    .Select(x => x.Dude); 

마지막으로, 리안은 친구 정말?

관련 문제