How to group an IEnumerable <T> using a combined key selector?

I am looking for the easiest way to group list items using the IEnumerable property of list items. For example, a list contains products, each product contains a list of updates. Two products must be grouped if they have the same identifier, and their upgrade property contains the same identifiers. I managed to do this with a special EqualityComparer, but I wonder if there is an easier way to do this?

My current working code is:

public class Product
 {
    public int ProductId { get; set; }
    public string Name { get; set; }
    public IEnumerable<Upgrade> Upgrades { get; set; }
 }

 public class Upgrade
 {
    public int Id { get; set; }
    public string Name { get; set; }
 }

 public class ProductsEqualityComparer : IEqualityComparer<Product>
 {      
    public bool Equals(Product x, Product y)
    {
     bool areProductsIdsEqual = x.ProductId == y.ProductId;
     bool areUpgradesEqual = new HashSet<int>(x.Upgrades.Select(u => u.Id)).SetEquals(y.Upgrades.Select(u2 => u2.Id));
     return areProductsIdsEqual && areUpgradesEqual;
    }

    public int GetHashCode(Product obj)
    {
     int hash = obj.ProductId.GetHashCode();
     foreach (var upgrade in obj.Upgrades)
     {
        hash ^= upgrade.Id.GetHashCode();
     }
     return hash;
    }
 }

Then I just call it like this:

var grouped = productList.GroupBy(l => l, new ProductsEqualityComparer());

For all Linq gurus - is there an easier / better way to do this?

+4
source share
1

, , . , , :

var grouped = productList.Select(p => new {
        GroupId = p.ProductId.ToString() + ";" + String.Join(",", p.Upgrades.Distinct().OrderBy(u => u)),
        Product = p
    }.GroupBy(
        p => p.GroupId, 
        p => p.Product
    );

, GroupId . GroupId, , , .

+3

Source: https://habr.com/ru/post/1653571/


All Articles