Как сгруппировать значения 2 в общий список VB.NET? - PullRequest
1 голос
/ 18 августа 2010

Я использую VB.NET на Framework 2.0. Я хочу быстро сгруппировать общий список <> по двум свойствам. Для примера расскажем, что у меня есть список типа ордера со свойствами CustomerId, ProductId и ProductCount. Как получить среднее значение ProductCounts, сгруппированных по CustomerId и ProductId в VB.NET?

К сожалению, я не могу сделать это на уровне БД (что было бы легко). Также я не могу использовать LINQ или Lambada как Im на Framewwork 2.0. Поэтому мне нужно сделать это на уровне приложения в VB.net. Список возвращается мне, отсортированный по CustomerId и ProductId, так что я предполагаю, что с помощью нескольких циклов sI сможет создать среднее значение, но должен быть более чистый способ сделать это?

1 Ответ

1 голос
/ 18 августа 2010

Этот тип проблемы является отличным примером того, почему LINQ был представлен в C # и VB.NET. В .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().

.

Очевидно, что вы могли бы продолжить этот путь абстракции, чтобы лучше повторно использовать свой код, но я думаю, что это дает вам хорошее начало.

...