我在Framework 2.0上使用VB.NET。我想快速分组通用列表<>由两个属性。为了这个例子,我假设我有一个Order类型的List,其中包含CustomerId,ProductId和ProductCount属性。我如何获得在VB.NET中按CustomerId和ProductId分组的ProductCounts的平均值?
不幸的是,我不能在数据库级别这样做(这本来很容易)。另外,我不能在Framewwork 2.0上使用LINQ或Lambada作为Im。所以我需要在VB.net的应用程序级别执行此操作。列表返回给我按CustomerId和ProductId排序,所以我想有几个循环sI应该能够创建一个平均值但是必须有一个更简洁的方法来做到这一点?
答案 0 :(得分:1)
这种类型的问题是为什么在C#和VB.NET中引入LINQ的一个很好的例子。在.NET 3.5及更高版本中,LINQ提供了解决此问题的“更清洁的方法”。
不幸的是,因为您使用的是.NET 2.0,所以您将以或多或少的“手动”方式解决问题。但是,您仍然可以通过将要查找的功能封装到明确定义的类和方法中来编写干净的代码。这是LINQ的一个(但不是唯一的)优点,即它以干净,声明的方式封装了您期望的功能。
以下是一些示例代码,可帮助您入门:
'The AggregateItem and AggregateItems classes will help encapsulate the '
'the functionality you are looking for.'
Public Class AggregateItem
Public Property GroupByProperty1 As Integer ' Get/Set code...'
Public Property GroupByProperty2 As Integer ' Get/Set code...'
Public Property Values As List(Of Double) = New List(Of Double()() _
' Get/Set code...'
Public Function GetAverage() As Double
'Code to calculate and return Average...'
End Function
End Class
Public Class AggregateItems
Public Property AggregateItemList As List(Of AggregateItem) = _
New List(Of AggregateItem)() ' Get/Set code...'
Public Sub InsertAggregateItem(groupByProperty1 As Integer, _
groupByProperty2 As Integer, _
value As Double)
Dim aiExisting As AggregateItem
aiExisting = GetMatchingAggregateItem(groupByProperty1, _
groupByProperty2)
If Not aiExisting Is Nothing Then
aiExisting.Values.Add(value)
Else
aiExisting = New AggregateItem
aiExisting.GroupByProperty1 = groupByProperty1
aiExisting.GroupByProperty2 = groupByProperty2
aiExisting.Values.Add(value)
AggregateItemList.Add(aiExisting)
End Sub
Private Function GetMatchingAggregateItem(groupByProperty1 As Integer, _
groupByProperty2 As Integer) _
As AggregateItem
Dim aiMatch As AggregateItem = Nothing
For Each ag As AggregateItem in AggregateItemList
If ag.GroupByProperty1 = groupByProperty1 AndAlso _
ag.GroupByProperty2 = groupByProperty2 Then
aiMatch = ag
Exit For
End If
Next
Return aiMatch
End Function
Enc Class
'Then, to consume these classes....'
Public Module MyProgram
Public Sub Main()
Dim aItems As New AggregateItems()
'Say you have List(Of Order) named listOfOrders'
'We will loop through that list, insert the grouping IDs and values'
'into our AggregateItems object'
For Each o As Order In listOfOrders
aItems.InsertAggregateItem(o.OrderId, o.ProductId, o.ProductCount)
Next
'Now we can loop through aItems to cleanly get the average: '
For Each ai As AggregateItem in aItems.AggregateItemsList
Console.WriteLine("Order: {0} Product: {1} Average: {2}", _
ai.GroupByProperty1, ai.GroupByProperty2, _
ai.GetAverage())
Next
End Sub
End Module
将数据插入到封装良好的类中的好处是消费代码非常简洁易懂。此外,由于您已将数据汇总到AggregateItem
类,因此您可以使用GetSum()
或GetMax()
等更多方法轻松扩展该类。
显然,你可以继续这条抽象路径,以便更好地重用代码,但我认为这会给你一个良好的开端。