Comment faire une requête Linq de regroupement sur des clés multiples en VB .Net ?
De ORSWiki
' En Visual Basic .Net, la syntaxe du regroupement sur des clés multiples ' est aussi simple qu'en C# :
Dim personnes() = { _ New With {.Nom = "Pierre", .Masculin = True, .Pays = "France", .Capital = 10}, _ New With {.Nom = "Paul", .Masculin = True, .Pays = "France", .Capital = 15}, _ New With {.Nom = "Françoise", .Masculin = False, .Pays = "France", .Capital = 20}, _ New With {.Nom = "John", .Masculin = True, .Pays = "Amerique", .Capital = 25}}
Dim cumulCapitalParGenreEtPays = From personne In personnes _ Group By personne.Masculin, personne.Pays _ Into Group Select New With { _ .Masculin = Masculin, _ .Pays = Pays, _ .CapitalParGenreEtPays = Group.Sum(Function(p) p.Capital), _ .NbPersonnes = Group.Count()} Debug.WriteLine("Calcul juste :") For Each total In cumulCapitalParGenreEtPays Debug.WriteLine("Total " & _ "Masculin=" & total.Masculin & " x " & _ total.Pays & " : " & _ total.CapitalParGenreEtPays & " (" & total.NbPersonnes & " personne(s))") Next
' Je ne sais pas si Visual Studio a été corrigé, mais avant (VB 2010 ou 2008 ?) ' ce n'était pas aussi simple : ' En Visual Basic .Net, la syntaxe du regroupement sur des clés multiples n'était pas aussi ' intuitive qu'en C#, il fallait utiliser le mot clé Key au bon endroit, sinon le regroupement ' ne se faisait pas : Dim cumulCapitalParGenreEtPays2 = From personne In personnes _ Group By clef = New With {Key personne.Masculin, Key personne.Pays} _ Into Group Select New With { _ .Regroupement = clef, _ .CapitalParGenreEtPays = Group.Sum(Function(p) p.Capital), _ .NbPersonnes = Group.Count()} Debug.WriteLine("Calcul juste (2) :") For Each total In cumulCapitalParGenreEtPays2 Debug.WriteLine("Total " & _ "Masculin=" & total.Regroupement.Masculin & " x " & _ total.Regroupement.Pays & " : " & _ total.CapitalParGenreEtPays & " (" & total.NbPersonnes & " personne(s))") Next
' Sans utiliser le mot clé Key, c'est possible aussi, mais la syntaxe n'est pas aussi simple : Dim cumulCapitalParGenreEtPays3 = From personne In personnes _ Group By clef = _ New With {personne.Masculin}.Masculin, _ New With {personne.Pays}.Pays _ Into Group Select New With { _ .Regroupement = clef, _ .Pays = Pays, _ .CapitalParGenreEtPays = Group.Sum(Function(p) p.Capital), _ .NbPersonnes = Group.Count()} Debug.WriteLine("Calcul juste (3) :") For Each total In cumulCapitalParGenreEtPays3 Debug.WriteLine("Total " & _ "Masculin=" & total.Regroupement & " x " & _ total.Pays & " : " & _ total.CapitalParGenreEtPays & " (" & total.NbPersonnes & " personne(s))") Next
' Voici un exemple dans lequel le regroupement ne se fait pas : Dim cumulCapitalParGenreEtPays4 = From personne In personnes _ Group By clef = New With {personne.Masculin, personne.Pays} _ Into Group Select New With { _ .Regroupement = clef, _ .CapitalParGenreEtPays = Group.Sum(Function(p) p.Capital), _ .NbPersonnes = Group.Count()} Debug.WriteLine("Calcul faux (pas de regroupement) :") For Each total In cumulCapitalParGenreEtPays4 Debug.WriteLine("Total " & _ "Masculin=" & total.Regroupement.Masculin & " x " & _ total.Regroupement.Pays & " : " & _ total.CapitalParGenreEtPays & " (" & total.NbPersonnes & " personne(s))") Next
' Résultats:
' Calcul juste ' Total Masculin=True x France : 25 (2 personne(s)) ' Total Masculin=False x France : 20 (1 personne(s)) ' Total Masculin=True x Amerique : 25 (1 personne(s))
' Calcul faux (pas de regroupement) : ' Total Masculin=True x France : 10 (1 personne(s)) ' Total Masculin=True x France : 15 (1 personne(s)) ' Total Masculin=False x France : 20 (1 personne(s)) ' Total Masculin=True x Amerique : 25 (1 personne(s))
' Enfin, voici la syntaxe correcte avec les expressions Lambda (le résultat est le même) : Debug.WriteLine("Calcul juste (lambda) :") Dim cumulCapitalParGenreEtPaysLambda = personnes _ .GroupBy(Function(personne) New With {Key personne.Masculin, Key personne.Pays}) _ .Select(Function(regroupement) New With { _ .Regroupement = regroupement.Key, _ .NbPersonnes = regroupement.Count, _ .CapitalParGenreEtPays = regroupement.Sum(Function(c) c.Capital)}) For Each total In cumulCapitalParGenreEtPaysLambda Debug.WriteLine("Total " & _ "Masculin=" & total.Regroupement.Masculin & " x " & _ total.Regroupement.Pays & " : " & _ total.CapitalParGenreEtPays & " (" & total.NbPersonnes & " personne(s))") Next