2010-08-18 2 views
1

J'utilise VB.NET sur Framework 2.0. Je cherche à grouper rapidement une liste générique <> par deux propriétés. Pour les besoins de cet exemple, disons que j'ai un type Liste d'un ordre avec les propriétés de CustomerId, ProductId et ProductCount. Comment puis-je obtenir la moyenne des ProductCounts groupés par CustomerId et ProductId dans VB.NET?Comment GroupBy 2 valeurs dans une liste générique, VB.NET?

Malheureusement, je ne peux pas le faire au niveau DB (ce qui aurait été facile). Aussi, je ne peux pas utiliser LINQ ou Lambada comme Im sur Framewwork 2.0. Donc, je dois le faire au niveau de l'application dans VB.net. La liste me revient triée par CustomerId et ProductId donc je suppose qu'avec quelques boucles, je devrais être capable de créer une valeur moyenne, mais il doit y avoir une façon plus propre de faire cela?

Répondre

1

Ce type de problème est un excellent exemple de la raison pour laquelle LINQ a été introduit en C# et VB.NET. Dans .NET 3.5 et versions ultérieures, LINQ fournit la "méthode plus propre" que vous recherchez pour résoudre ce problème.

Malheureusement, parce que vous utilisez .NET 2.0, vous aurez résolu le problème de façon plus ou moins "manuelle". Cependant, vous pouvez toujours écrire du code propre en encapsulant la fonctionnalité que vous recherchez dans des classes et des méthodes bien définies. C'est l'un (mais pas le seul) des avantages de LINQ, c'est-à-dire qu'il encapsule les fonctionnalités que vous attendez d'une manière propre et déclarative.

Voici quelques exemples de code pour vous aider à démarrer:

'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 

La bonne chose sur l'insertion de vos données dans des classes bien encapsulées est que le code est très succincte consommation et facile à comprendre. En outre, puisque vos données sont déjà agrégées dans une classe AggregateItem, vous pouvez facilement étendre cette classe avec d'autres méthodes telles que GetSum() ou GetMax(). De toute évidence, vous pouvez continuer sur cette voie de l'abstraction pour obtenir une meilleure réutilisation de votre code, mais je pense que cela vous donne un bon début.

+0

Thanx Ben. Je n'ai pas eu besoin d'agréger sur les données, nous allons aborder cela d'une manière différente puisque nous allons mettre à jour notre application à 3.5 de toute façon plus tard .. Votre solution semble être quelque chose à essayer pour d'autres problème similaire que j'avais! :) – Mcad001

+0

@Mcad Bon à savoir que vous êtes en train de mettre à niveau. Je ne pense pas qu'il y ait une chance que vous puissiez convaincre votre équipe de passer à la version 4.0? –

Questions connexes