我必须编写一个方法,返回按这些对象的某些属性分组的对象列表。我可以使用 linq 的 GroupBy 成功实现它,但使用匿名类型,我无法将其发送回调用者。如果我尝试使用类来存储 IGrouping 部分,如 here 中的建议, .GroupBy 根本不分组 - 就像缺少 Key 关键字一样,但我无法在强类型类中使用它们。
我搜索了很多 - 更多的是因为我懒得写问题,而不是因为遵循 stackoverflow 问题指南 - 但我发现的大多数内容要么与 C# 相关,但没有问题Key 关键字的,或者它是关于单列 GroupBy 的,或者它使用匿名类型,因为它不关心从函数或子函数返回参数,所以我编写了一个小程序来说明这种情况。
Imports System.Globalization
Module Module1
Public Class TrackHist
Public Property Data As DateTime
Public Property Esdvn As String
Public Property Cmnts As String
Public Property IdCnt As String
End Class
Public Class GroupedTrack
Public Property Data As DateTime
Public Property Esdvn As String
End Class
Function Group(lista As List(Of TrackHist)) As List(Of IGrouping(Of GroupedTrack, List(Of TrackHist)))
Return lista.GroupBy(Function(f) New GroupedTrack With {.Data = f.Data, .Esdvn = f.Esdvn}).ToList
End Function
Sub Main()
Dim array As New List(Of TrackHist)
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("10/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "BIL", .IdCnt = "CN134234"})
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("10/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "BIL", .IdCnt = "CN284235"})
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("10/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "BIL", .IdCnt = "CN660003"})
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("12/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "LOA", .IdCnt = "CN134234"})
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("12/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "LOA", .IdCnt = "CN284235"})
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("13/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "LOA", .IdCnt = "CN660003"})
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("15/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "INSP", .IdCnt = "CN134234"})
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("16/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "DEP", .IdCnt = "CN284235"})
array.Add(New TrackHist() With {.Data = DateTime.ParseExact("16/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "DEP", .IdCnt = "CN660003"})
Dim groupedAnonymous = array.GroupBy(Function(f) New With {Key f.Data, Key f.Esdvn}).ToList
Dim groupedTyped = Group(array)
Console.WriteLine("Grouped anonymous: {0} registers", groupedAnonymous.Count)
Console.WriteLine("Grouped typed: {0} registers", groupedTyped.Count)
End Sub
End Module
该程序产生以下输出:
匿名分组:5 个寄存器 分组类型:9个寄存器
或者,换句话说,强类型对象的分组根本就不是分组。那么,在 VB.Net 中制作一个可以从函数返回结果的 GroupBy 的正确方法是什么?
最佳答案
将 Slai 和 Mark 的评论转换为答案:
您的问题是您尚未定义将 GroupedTrack
对象与另一个 GroupedTrack
对象进行比较的方法;因此,当创建这些对象时,它们会通过引用进行比较,并且因为它们实际上都是不同的对象,所以您会得到 9 个不同的值。
您要做的就是重写 Equals()
和 GetHashCode()
函数,以便编译器现在如何比较 GroupedTrack
按值排列的对象。
类似这样的事情:
Public Class GroupedTrack
Public Property Data As DateTime
Public Property Esdvn As String
Public Overrides Function Equals(obj As Object) As Boolean
If obj Is Nothing Then Return False
If TypeOf obj IsNot GroupedTrack Then Return False
Return Me.Data = CType(obj, GroupedTrack).Data And Me.Esdvn = CType(obj, GroupedTrack).Esdvn
End Function
Public Overrides Function GetHashCode() As Integer
Return (Me.Data.ToString() & Me.Esdvn).GetHashCode()
End Function
End Class
(当你这样做时,将你的函数定义更正为
Function Group(lista As List(Of TrackHist)) As List(Of IGrouping(Of GroupedTrack, TrackHist))
)
这样,两个分组都会生成一个包含 5 个元素的列表。
关于vb.net - 如何在 VB.Net 中创建一个可以从函数返回结果的 GroupBy?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41266714/