LINQ 按总和分组未按预期工作

LINQ group by sum not working as expected

我有这个class:

public class tempClass
{
    public int myKey { get; set; }
    public int total { get; set; }
}

分组和求和的代码:

var list = new List<tempClass>();
list.Add(new tempClass { myKey = 1, total = 1 });
list.Add(new tempClass { myKey = 1, total = 2 });
list.Add(new tempClass { myKey = 2, total = 3 });
list.Add(new tempClass { myKey = 2, total = 4 });
list = list
    .Select(w => new tempClass { myKey = w.myKey, total = w.total })
    .GroupBy(x => new tempClass { myKey = x.myKey })
    .Select(y => new tempClass { myKey = y.Key.myKey, total = y.Sum(z => z.total) })
    .ToList();

list 计数在 GroupBy 之后仍然是 4。

以下代码的相同结果:

list = list
    .GroupBy(x => new tempClass { myKey = x.myKey })
    .Select(y => new tempClass { myKey = y.Key.myKey, total = y.Sum(z => z.total) })
    .ToList();

原因是您按 class 分组,它不会覆盖 EqualsGetHashCode。然后使用 System.Object 的实现,它只比较引用。由于所有都是不同的引用,因此您为每个实例获得一组。

您可以按此 属性 分组或覆盖 EqualsGetHashCode 以比较此 属性:

list = list
    .Select(w => new tempClass { myKey = w.myKey, total = w.total })
    .GroupBy(x => x.myKey)
    .Select(y => new tempClass { myKey = y.Key, total = y.Sum(z => z.total) })
    .ToList();

不需要两行 Select 行,一行就够了。在 GroupBy 中,只是 select 你的密钥,不要在那里创建你的 class 的新对象:

list = list
       .GroupBy(x => x.myKey)
       .Select(y => new tempClass { myKey = y.Key, total = y.Sum(z => z.total) })
       .ToList();

这是声明式查询语法版本:

list = (from x in list
        group x by x.myKey into g
        select new tempClass { myKey = g.Key, total = g.Sum(z => z.total) }).ToList();

天哪,您在 LINQ 语句中创建了很多新的 TempClass 对象,是吗?

您没有得到正确结果的原因是您的 GroupBy 没有将具有相等 TempClass.MyKey 的 TempClass 对象分组,但具有相等的 TempClass。

TempClass 的默认 EqualityComparer 声明两个 TempClass 对象相等(如果它们是同一对象),从而使两个 TempClass 对象不相等,即使它们具有相同的值也是如此。

您的查询应该是:

var result = list
    .GroupBy(listItem => listItem.MyKey) // make groups with equal MyKey
    .Select(group => new                 // from every group make one new item
    {
         Key = group.Key,   // with key the common MyKey in the group
         GrandTotal = group.Sum(groupItem => groupItem.Total);
                            // and value the sum of all Total values in the group
    });

我选择不让最终结果项目成为 TempClass 序列,因为我不确定您是否会将具有此 GrandTotal 的项目视为 TempClass 对象。但是如果你愿意,你可以改变最后的 select:

 .Select(group => new TempKey()
 {
     Key = group.Key,
     Total = group.Sum(groupItem => groupItem.Total);
 });