I spent a lot of time on this problem. I am able to do simple Group By LINQ queries (on one property) but for multiple fields I'm a little stuck... Here is a LINQPad sample of what I want to do :
dim lFinal={new with {.Year=2010, .Month=6, .Value1=0, .Value2=0},
new with {.Year=2010, .Month=6, .Value1=2, .Value2=1},
new with {.Year=2010, .Month=7, .Value1=3, .Value2=4},
new with {.Year=2010, .M开发者_如何学Goonth=8, .Value1=0, .Value2=1},
new with {.Year=2011, .Month=1, .Value1=2, .Value2=2},
new with {.Year=2011, .Month=1, .Value1=0, .Value2=0}}
Dim lFinal2 = From el In lFinal
Group el By Key = new with {el.Year,el.Month}
Into Group
Select New With {.Year = Key.Year, .Month=Key.Month, .Value1 = Group.Sum(Function(x) x.Value1), .Value2 = Group.Sum(Function(x) x.Value2)}
lFinal.Dump()
lFinal2.Dump()
The lFinal list has 6 items, I want the lFinal2 to have 4 items : 2010-6 and 2011-1 should group.
Thanks in advance.
Make the properties in the anonymous type immutable using the Key
keyword and then they will be used for comparisons
Dim lFinal2 = From el In lFinal
Group el By Key = new with {key el.Year, key el.Month}
Into Group
Select New With {
.Year = Key.Year,
.Month = Key.Month,
.Value1 = Group.Sum(Function(x) x.Value1),
.Value2 = Group.Sum(Function(x) x.Value2)
}
Thanks ! But I noticed I needed to also write the GetHashCode function to make it works. I provide the VB.Net translation of the final class + LINQ GroupBy :
Class :
Public Class YearMonth
Implements IEquatable(Of YearMonth)
Public Property Year As Integer
Public Property Month As Integer
Public Function Equals1(other As YearMonth) As Boolean Implements System.IEquatable(Of YearMonth).Equals
Return other.Year = Me.Year And other.Month = Me.Month
End Function
Public Overrides Function GetHashCode() As Integer
Return Me.Year * 1000 + Me.Month * 100
End Function
End Class
And the LINQ query :
Dim lFinal2 = From el In lFinal
Group el By Key = New YearMonth With {.Year = el.Year, .Month = el.Month}
Into Group
Select New ItemsByDates With {.Year = Key.Year,
.Month = Key.Month,
.Value1 = Group.Sum(Function(x) x.Value1),
.Value2 = Group.Sum(Function(x) x.Value2)}
Not 100% sure but group by probably uses the Equals() and/or GetHashCode implementation, so when you do the implicit creation:
= Group el By Key = new with {el.Year,el.Month}
the implicit object doesn't know to check both year and month (just because it has the properties doesn't mean it checks them when comparing to other objects).
So you'll probably need to do something more like this:
= Group el By Key = new CustomKey() { Year = el.Year, Month = el.Month };
public class CustomKey{
int Year { get; set; }
int Month { get; set; }
public override bool Equals(obj A) {
var key (CustomKey)A;
return key.Year == this.Year && key.Month == this.Month;
}
}
精彩评论