2010-08-18 2 views
1

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

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

ответ

1

Этот тип проблемы является отличным примером того, почему 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().

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

+0

Thanx Ben. Мне не нужно было агрегировать данные, мы подойдем к этому по-другому, так как мы все равно обновим наш appz до 3.5. Ваше решение кажется чем-то другим, чтобы попробовать, если они столкнутся с проблемой аналогичная проблема, которая у меня была! :) – Mcad001

+0

@Mcad Приятно слышать, что вы обновляете. Я не думаю, что есть шанс, что вы сможете убедить свою команду идти вперед и обновиться до 4.0? –