LINQ组总和不按预期工作

时间:2018-04-20 07:38:02

标签: c# .net linq .net-4.0

我有这堂课:

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();

3 个答案:

答案 0 :(得分:4)

原因是您按照不会覆盖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();

答案 1 :(得分:2)

您不需要两条Select行,一条就足够了。在GroupBy内,只需选择你的密钥,不要在那里创建一个新的对象:

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();

答案 2 :(得分:1)

我的,你在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
    });

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

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