2014-10-31 3 views
1

여러 열로 컬렉션을 그룹화합니다.LINQ 중첩 된 컬렉션이있는 여러 열을 그룹화합니다.

var groupedAirProducts = airproductsPerClient.GroupBy(ac => new 
{ 
    ac.AirProduct.PassengerNameRecord, 
    ac.AirProduct.Flights.First().MarketingAirlineCode, 
    ac.AirProduct.Flights.First().FlightNo, 
    ac.AirProduct.Flights.First().DepartureDate 
}) 

문제는 내가 첫 비행에 의해서만 그룹에 싶지 않아,하지만 난 모든 항공편을 포함 할 : 그들은 중첩이 같은 수준에있는 경우이 그룹을 쉽게합니다. 제가하고 싶은 것은 다음과 같습니다 :

var groupedAirProducts= airproductsPerClient.GroupBy(ac => 
{ 
    ac.AirProduct.PassengerNameRecord, 
    foreach(var flight in ac.AirProduct.Flights){ 
     flight.MarketingAirlineCode, 
     flight.FlightNo, 
     flight.DepartureDate 
    } 
}) 

위의 코드는 단지 아이디어의 실례입니다. 그것은 작동/적절한 코드가 아닙니다. 내가 그것을하는 방법을 아는 유일한 방법은 꽤 추하고 복잡합니다. LINQ 나이 문제를 해결할 수있는 간단한 방법을 사용하여 좋은 방법이 있는지 궁금합니다.

편집 : 더 많은 것을 설명합니다. 그룹화의 결과로 동일한 PassengerNameRecord를 공유하는 airProducts 콜렉션이 있고 주어진 Air Product에 속한 항공편이 동일한 MarketingAirlineCode, FlightNo, DepartureDate를 공유하고 싶습니다. 나는 PassengerNameRecord 콜렉션을 아첨하여 구현하는 방법을 알고 있으므로 항공편이 그룹화되어 그룹화 된 속성을 공유하는 항공 제품 그룹이 있습니다. 그리고 나서 기분 좋은 구조를 재건합니다. 일부 컬렉션을 반복하여 groupBy 속성을 추가하거나 그룹화 된 컬렉션을 병합하는 방법이 필요합니다. 컬렉션을 PassengerNameRecord로 그룹화하고 컬렉션을 Flight 속성 및 병합별로 그룹화하는 방법이 있다면 그들과 함께, 불행히도 나는 그러한 병합을하는 쉬운 방법이 있는지 의심 스럽다.

+1

는 "쉬운 그룹에"part의 컴파일되지 않습니다. 익명 유형을 사용해야합니다. –

+0

그래서 기본적으로 컬렉션별로 그룹화하려고합니다 (+'PassengerNameRecord')? 적절한'GetHashCode'와'Equals'를 가지고'IEqualityComparer '을 구현하는 클래스를 생성하십시오. 'T'는 하나의'airproductsPerClient'의 타입입니다. –

+0

그룹화가 어떻게 작동하는지 이해하지 못합니다. 특정 엔터티를 단일 그룹으로 묶어야합니다. 예를 들어, 여러 번 비행 한 경우, 동일한 엔티티를 할당해야하는 여러 개의 그룹으로 끝날 수 있습니다. 더 이상 그룹화되지 않으므로이 방법에 대한 정보를 더 제공 할 수 있습니다. – decPL

답변

1

다음 그룹이 (의사 코드) 같은 항공편.

다음과 같은 방법으로 그것을 구현할 수 있습니다

public class AirClientComparer : IEqualityComparer<AirClient> 
{ 
    public bool Equals(AirClient lhs, AirClient rhs) 
    { 
     if (lhs == null || rhs == null) return false; 
     if(object.ReferenceEquals(lhs, rhs)) return true; 
     if(lhs.PassengerNameRecord != rhs.PassengerNameRecord) return false; 
     if(object.ReferenceEquals(lhs.AirProduct, rhs.AirProduct)) return true; 
     if(lhs.AirProduct == null || rhs.AirProduct == null) return false; 
     if(object.ReferenceEquals(lhs.AirProduct.Flights , rhs.AirProduct.Flights)) return true; 
     if(lhs.AirProduct.Flights.Count != rhs.AirProduct.Flights.Count) return false; 
     if(lhs.AirProduct.Flights.Count == 0 && rhs.AirProduct.Flights.Count == 0) return true; 
     return lhs.AirProduct.Flights.All(f => 
      rhs.AirProduct.Flights.Any(f2 => 
        f.MarketingAirlineCode == f2.MarketingAirlineCode 
       && f.FlightNo == f2.FlightNo 
       && f.DepartureDate == f2.DepartureDate)); 
    } 

    public int GetHashCode(AirClient obj) 
    { 
     if(obj.AirProduct == null) return 0; 
     int hash = obj.AirProduct.PassengerNameRecord == null 
        ? 17 : 17 * obj.AirProduct.PassengerNameRecord.GetHashCode(); 
     unchecked 
     { 
      foreach(var flight in obj.AirProduct.Flights) 
      { 
       hash = (hash * 31) + flight.MarketingAirlineCode == null ? 0 : flight.MarketingAirlineCode.GetHashCode(); 
       hash = (hash * 31) + flight.FlightNo == null ? 0 : flight.FlightNo.GetHashCode(); 
       hash = (hash * 31) + flight.DepartureDate.GetHashCode(); 
      } 
     } 
     return hash; 
    } 
} 

지금 당신이 GroupBy 예를 들면 사용할 수 있습니다 :

var groupedAirProducts = airproductsPerClient.GroupBy(ac => new AirClientComparer()); 
+0

이것은 정말로 문제를 다루는 좋은 방법입니다.해결책으로 백만 달러 감사드립니다. –

0

그런 경우 내부 테이블로 시작해야합니다. 내부 표는 당신이이

ICollection<Flight> Flights

AirProduct에 당신은 또한 Flight의 내부 Airproduct 회원 필요가 그런 것처럼, 외부 테이블에 대한 참조를 필요로한다. 당신은 사용자 정의 GroupBy (또는 다른 LINQ 방법)에 대한 IEqualityComparer<AirClient>을 구현할 수

AirProduct.Flights.groupby(flight => new{ flight.MarketingAirlineCode, 
     flight.FlightNo, 
     flight.DepartureDate, 
     flight.product.PassengerNameRecord 
}); 
관련 문제