web-dev-qa-db-fra.com

Créer un dictionnaire sur une liste avec regroupement

J'ai l'objet suivant dans une liste:

public class DemoClass
{
    public int GroupKey { get; set; }
    public string DemoString { get; set; }
    public object SomeOtherProperty { get; set; }
}

Maintenant, je veux créer le dictionnaire suivant à partir de celui-ci:

Dictionary<int, List<DemoClass>>

Je veux regrouper les List<DemoClass> par la propriété GroupKey, mais je ne comprends pas comment cela se fait et un peu d'aide.

Après avoir réfléchi un peu, j'ai atteint le comportement nécessaire avec:

var groupedDemoClasses = from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                            group demoClass by demoClass.GroupKey
                            into groupedDemoClass
                            select groupedDemoClass;
var neededDictionary = groupedDemoClass.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

mais, y a-t-il un moyen d'en faire une seule déclaration?

99
var groupedDemoClasses = (from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                          group demoClass by demoClass.GroupKey
                          into groupedDemoClass
                          select groupedDemoClass).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Celui-ci fonctionnera !!!

82

Juste pour faire suggestion de mquander concret:

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .GroupBy(x => x.GroupKey)
                             .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Vous le raccourciriez si vous utilisiez aussi des noms de variables plus courts, bien sûr :)

Cependant, pourrais-je suggérer qu'un Lookup pourrait être plus approprié? Une recherche est essentiellement un dictionnaire d'une clé vers un IEnumerable<T> - sauf si vous avez vraiment besoin des valeurs sous forme de liste, cela rend le code encore plus court (et plus efficace) avec le ToLookup appel:

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);
187
Jon Skeet

Vous en avez déjà fait une doublure. Mettez simplement le ToDictionary à la fin de votre première ligne. Si vous souhaitez qu'il soit plus court, utilisez la syntaxe de composition fonctionnelle au lieu de la syntaxe de requête.

6
mqp

Je vais légèrement hors sujet ici, mais je suis arrivé à ce fil parce que je cherchais un moyen de créer un dictionnaire d'un dictionnaire dans Linq, et la conversation ici m'a conduit à la réponse .. .

Vous pouvez utilisez linq pour créer des dictionnaires à plusieurs niveaux, ce qui est utile pour les scénarios où vous avez plus de 1 clé ou dimension que vous souhaitez rechercher. L'astuce consiste à créer un regroupement, puis à le convertir en dictionnaire, comme suit:

  Dim qry = (From acs In ActualSales _
             Group By acs.ProductID Into Group _
             Select ProductID, Months = Group.ToDictionary(Function(c) c.Period) _
            ).ToDictionary(Function(c) c.ProductID)

La requête résultante peut être utilisée comme suit:

 If qry.ContainsKey(_ProductID) Then
      With qry(_ProductID)
          If .Months.ContainsKey(_Period) Then
             ...
          End If
      End With
 End If

J'espère que cela sera utile à toute autre personne qui a besoin de ce type de requête.

3
Mark