linq distinct or group by multiple properties
While a new anonymous type will work, it might make more sense, be more readable, and consumable outside of your method to either create your own type or use a Tuple. (Other times it may simply suffice to use a delimited string: string.Format({0}.{1}, g.Title, g.Price)
)
List<Product> result = pr.GroupBy(g => new Tuple<string, decimal>(g.Title, g.Price))
.ToList();
List<Product> result = pr.GroupBy(g => new ProductTitlePriceGroupKey(g.Title, g.Price))
.ToList();
As for getting the result set you want, the provided answer suggests just returning the first, and perhaps that's OK for your purposes, but ideally you'd need to provide a means by which Color
is aggregated or ignored.
For instance, perhaps you'd rather list the colors included, somehow:
List<Product> result = pr
.GroupBy(g => new Tuple<string, decimal>(g.Title, g.Price))
.Select(x => new Product()
{
Title = x.Key.Item1,
Price = x.Key.Item2,
Color = string.Join(", ", x.Value.Select(y => y.Color) // "Red, Green"
})
.ToList();
In the case of a simple string property for color, it may make sense to simply concatenate them. If you had another entity there, or simply don't want to abstract away that information, perhaps it would be best to have another entity altogether that has a collection of that entity type. For instance, if you were grouping on title and color, you might want to show the average price, or a range of prices, where simply selecting the first of each group would prevent you from doing so.
List<ProductGroup> result = pr
.GroupBy(g => new Tuple<string, decimal>(g.Title, g.Price))
.Select(x => new ProductGroup()
{
Title = x.Key.Item1,
Price = x.Key.Item2,
Colors = x.Value.Select(y => y.Color)
})
.ToList();
It's groups by needed properties and select:
List<Product> result = pr.GroupBy(g => new { g.Title, g.Price })
.Select(g => g.First())
.ToList();