如何对通用列表中的 2 个值进行 GroupBy,VB.NET?

发布于 2024-09-15 09:35:18 字数 372 浏览 2 评论 0原文

我在 Framework 2.0 上使用 VB.NET。我希望快速对通用列表进行分组<>由两个属性。在本示例中,假设我有一个 Order 类型的列表,其中包含 CustomerId、ProductId 和 ProductCount 属性。如何在 VB.NET 中获得按 CustomerId 和 ProductId 分组的 ProductCounts 的平均值?

不幸的是,我无法在数据库级别执行此操作(这很容易)。另外,我无法在 Framework 2.0 上使用 LINQ 或 Lambada。所以我需要在 VB.net 的应用程序级别执行此操作。该列表按 CustomerId 和 ProductId 排序返回给我,所以我想通过几个循环我应该能够创建平均值,但必须有一个更干净的方法来做到这一点?

I'm using VB.NET on Framework 2.0. I'm looking to quickly group a Generic List<> by two properties. For the sake of this example lets say I have a List of an Order type with properties of CustomerId, ProductId, and ProductCount. How would I get the average of ProductCounts grouped by CustomerId and ProductId in VB.NET ?

Unfortunatly I cannot do this at DB level (which would have been easy). Also I cannot use LINQ or Lambada as Im on Framewwork 2.0. So I need to do this at application level in VB.net. The list is returned to me sorted by CustomerId and ProductId so I guess with a few loop sI should be able to create a average value for but there must be a cleaner way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

叫思念不要吵 2024-09-22 09:35:18

此类问题是为什么在 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()< /代码>。

显然,您可以继续这条抽象路径,以更好地重用代码,但我认为这为您提供了一个良好的开端。

This type of problem is a great example of why LINQ was introduced in C# and VB.NET. In .NET 3.5 and above, LINQ provides the "cleaner way" that you are looking for to solve this problem.

Unfortunately, because you are using .NET 2.0, you'll have solve the problem in a more or less "manual" fashion. However, you can still write clean code by encapulating the functionality you are looking for into well-defined classes and methods. This is one (but not the only) of the benefits of LINQ, i.e. that it encapsulates the functionality you expect in a clean, declarative manner.

Here's some sample code to get you started:

'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

The nice thing about inserting your data into well-encapsulated classes is that the consuming code is very succinct and easy to understand. Also, since you already have your data aggregated into an AggregateItem class, you could easily extend that class with more methods such as GetSum() or GetMax().

Obviously, you could continue on this path of abstraction to get better re-use out of your code, but I would think that this gives you a good start.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文