Я группирую коллекцию по нескольким столбцам. Их легко группировать, если они находятся на том же уровне гнездования:
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 или простой способ решить эту проблему.
Изменение: объяснить больше того, что ожидается. В результате группировки я хочу иметь коллекции airProducts, которые используют один и тот же PassengerNameRecord, и что полеты, принадлежащие данному воздушному продукту, имеют одинаковый маркетингAirlineCode, FlightNo, DepartureDate. Я знаю, как реализовать его, льстив коллекции PassengerNameRecord, поэтому в нее включены рейсы, группируя их, поэтому у меня есть группы воздушных продуктов, которые разделяют сгруппированные свойства. А затем перестроить лестную структуру. Я надеялся, что есть способ либо добавить свойства groupBy, итерируя через некоторую коллекцию, либо есть способ объединить сгруппированную коллекцию - если есть способ собрать коллекцию с помощью PassengerNameRecord, а сбор, сгруппированный по свойствам Flight и слиянием их вместе, к сожалению, я сомневаюсь, что есть простой способ сделать такое слияние.
Вы можете реализовать пользовательский IEqualityComparer<AirClient>
для GroupBy
(или других методов LINQ).
Вы можете реализовать его следующим образом:
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());
В таких случаях вам нужно начать с внутренней таблицы. Внутренняя таблица также нуждается в ссылке на внешнюю таблицу, например, у вас есть
ICollection<Flight> Flights
в AirProduct
вам также нужен член Airproduct
внутри Flight
.
Затем группируйте свои полеты следующим образом (псевдокод)
AirProduct.Flights.groupby( flight => new{ flight.MarketingAirlineCode,
flight.FlightNo,
flight.DepartureDate,
flight.product.PassengerNameRecord
});
PassengerNameRecord
)? Создайте класс, который реализуетIEqualityComparer<T>
с правильнымGetHashCode
иEquals
.T
- это тип одногоairproductsPerClient
.