2011-08-04 11 views
1

다음과 같은 개체 그래프가 표시됩니다.LINQ (컬렉션 내의 컬렉션)로 코드 단순화

A --> B[] --> B1[] 
      --> B2[] 
    --> C[] 

난의 부재/속성에 대한 특정 조건을 확인해야 B1 및 B2뿐만 아니라 b2.Code C는 [] 내의 어딘가에 나타날 것을 보장한다. 모든 조건이 충족되면 C 및 B 배열 요소의 변수를 사용하여 새 객체를 생성해야합니다. 내 현재 시도는 아래에 표시되어 있지만이 LINQ 더 간결하게 만들 수 있을지 궁금해?

A a = GetA(); 
    List<MyTest> tsts = new List<MyTest>(); 
    foreach (B b in a.B) 
    { 
     foreach (B1 b1 in b.B1) 
     { 
      if (b1.State == ("READY")) 
      { 
       foreach (B2 b2 in b.B2) 
       { 
        var tst = (from c in a.C 
          where c.Code == b2.Code && !c.IsRedundant 
          select new MyTest 
          { 
           Code = c.Code, 
           BVal = b.BVal, 
           C1Val = c.C1      
          }).FirstOrDefault(); 
        if (tst != null) 
         tsts.Add(tst); 
        break; 
       } 
      } 
     } 
    } 

답변

2

물론입니다. 이에

var tests = from b in GetA().B 
      from b1 in b.B1 
      where b1.State == "READY" 
      from b2 in b.B2.Take(1) 
      from c in a.C 
         .Where(x => x.Code == b2.Code && !c.IsRedundant) 
         .Take(1) 
      select new MyTest 
      { 
       Code = c.Code, 
       BVal = b.BVal, 
       C1Val = c.C1      
      }; 

var testList = tests.ToList(); 

몇 가지 참고 사항 : 기본적으로 각각의 새로운 foreach 대략 추가 from 절에 동일시

  • 그것은 당신이 결코 실제로 b1을 사용하지 않고 있다는 것을 이상한 것 같다,하지만 당신은 추가를 만듭니다 각각의 b1에 대한 테스트 세트는 "준비"상태입니다. foreach (B2 b2 ...) 루프 내
  • 무조건 break은 기본적으로 우리는 오직 한 번 루프 본문을 실행 의미 - 따라서 Take(1)
  • 만 가장 안쪽 쿼리의 첫 번째 결과를 사용하는 방법이다 나는 내부 쿼리있어 왜 (표현 Take(1) 호출을 확장 메서드)를 통해 결과 최대 하나 얻을 수

그것은이 기이 중 일부는 제거 할 수 있음을 확실히 가능 -하지만 당신이 정말로 달성하려고하는지 분명하지 않다, 그래서 난 그냥했습니다 가능한 한 충실하게 원본 쿼리를 재현하도록 코드를 만들려고했습니다.

+0

감사합니다. 정말 유망 해 보입니다. 나는 이상한 점에 관해서는 코드를 게시하는 것이 조금 성급한 것이지만, 메모를 처리하기 위해; - 우리는 실제로 b1에서 아무것도 가져 가지 않습니다. 그러나 b1.State가 "READY"가 아니면 목록에 추가하고 싶지 않습니다. - FirstOrDefault와 break는 오직 0 또는 1과 일치하는 x가 있어야하므로 사용됩니다. 코드 == b2.Code. 따라서 일치하는 항목이 있으면이를 사용합니다. 그렇지 않으면 ** 가장 바깥 쪽 루프 (즉, b)에서 다음 항목을 처리해야합니다. 일반적으로 b1 배열에는 최대 2 개의 요소가 있으므로 휴식을 취하지 않았습니다. –