linq distinct或由多个属性分组

34 c# linq group-by distinct

如何使用c#和Linq result从下一个列表中获取:

 var pr = new List<Product>()
   {
       new Product() {Title="Boots",Color="Red",    Price=1},
       new Product() {Title="Boots",Color="Green",  Price=1},
       new Product() {Title="Boots",Color="Black",  Price=2},

       new Product() {Title="Sword",Color="Gray", Price=2},
       new Product() {Title="Sword",Color="Green",Price=2}
   };
Run Code Online (Sandbox Code Playgroud)

Result:

        {Title="Boots",Color="Red",  Price=1},               
        {Title="Boots",Color="Black",  Price=2},             
        {Title="Sword",Color="Gray", Price=2}
Run Code Online (Sandbox Code Playgroud)

我知道我应该使用GroupBy或者Distinct,但要了解如何获得所需的东西

   List<Product> result = pr.GroupBy(g => g.Title, g.Price).ToList(); //not working
   List<Product> result  = pr.Distinct(...);
Run Code Online (Sandbox Code Playgroud)

请帮忙

Ily*_*lya 84

它是按所需属性分组并选择:

List<Product> result = pr.GroupBy(g => new { g.Title, g.Price })
                         .Select(g => g.First())
                         .ToList();
Run Code Online (Sandbox Code Playgroud)


Joe*_*aus 6

虽然新的匿名类型可以工作,但它可能更有意义,更具可读性,并且可以在方法之外使用来创建您自己的类型或使用Tuple。(其他时候,使用分隔字符串可能就足够了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();
Run Code Online (Sandbox Code Playgroud)

至于获得您想要的结果集,提供的答案建议只返回第一个,也许这适合您的目的,但理想情况下您需要提供一种Color聚合或忽略的方法。

例如,也许您更愿意以某种方式列出所包含的颜色:

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();
Run Code Online (Sandbox Code Playgroud)

对于颜色的简单字符串属性,简单地将它们连接起来可能是有意义的。如果您在那里有另一个实体,或者只是不想抽象出该信息,那么最好是拥有另一个具有该实体类型集合的实体。例如,如果您根据标题和颜色进行分组,您可能想要显示平均价格或价格范围,而仅选择每组中的第一个就会阻止您这样做。

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();
Run Code Online (Sandbox Code Playgroud)