Reputation: 525
I have this class:
public class tempClass
{
public int myKey { get; set; }
public int total { get; set; }
}
Code to group by and sum:
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();
The list
count is still 4 after the GroupBy
.
Same result for code below:
list = list
.GroupBy(x => new tempClass { myKey = x.myKey })
.Select(y => new tempClass { myKey = y.Key.myKey, total = y.Sum(z => z.total) })
.ToList();
Upvotes: 2
Views: 2728
Reputation: 30492
My, you are creating a lot of new TempClass objects in your LINQ statement, don't you?
The reason that you don't get the correct result is that your GroupBy doesn't make groups of TempClass objects with the equal TempClass.MyKey, but with equal TempClass.
The default EqualityComparer for TempClass declares two TempClass objects equal if they are the same object, thus making two TempClass objects unequal, even if they have the same values.
Your query should be:
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
});
I chose not to make the final resulting items a sequence of TempClasses, because I'm not sure if you would consider items with this GrandTotal as TempClass objects. But if you want, you could change the final select:
.Select(group => new TempKey()
{
Key = group.Key,
Total = group.Sum(groupItem => groupItem.Total);
});
Upvotes: 1
Reputation: 25361
You don't need two Select
lines, one is enough. And inside GroupBy
, just select your key, don't create a new object of your class there:
list = list
.GroupBy(x => x.myKey)
.Select(y => new tempClass { myKey = y.Key, total = y.Sum(z => z.total) })
.ToList();
And here's the declarative-query-syntax version:
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();
Upvotes: 2
Reputation: 460238
The reason for this is that you group by a class which doesn't override Equals
and GetHashCode
. Then the implementation of System.Object
is used which just compares references. Since all are different references you get one group for every instance.
You could group by this property or override Equals
and GetHashCode
to compare this property:
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();
Upvotes: 4