web-dev-qa-db-fra.com

LINQ avec groupby et compter

C’est assez simple, mais j’en suis perdu: avec ce type de jeu de données:

UserInfo(name, metric, day, other_metric)

et cet exemple de données:

joe  1 01/01/2011 5
jane 0 01/02/2011 9
john 2 01/03/2011 0
jim  3 01/04/2011 1
jean 1 01/05/2011 3
jill 2 01/06/2011 5
jeb  0 01/07/2011 3
jenn 0 01/08/2011 7

Je voudrais récupérer un tableau qui répertorie les mesures dans l'ordre (0,1,2,3 ..) avec le nombre total de fois où le comptage a lieu. Donc, dans cet ensemble, vous vous retrouveriez avec:

0 3    
1 2    
2 2    
3 1

Je suis aux prises avec la syntaxe LINQ mais je suis coincé sur l'endroit où mettre un groupe et compter .... toute aide?

POST Edit: Je n'ai jamais réussi à obtenir les réponses affichées, car elles renvoyaient toujours un enregistrement avec le nombre de comptes différents. Cependant, j'ai pu créer un exemple LINQ to SQL qui a fonctionné:

        var pl = from r in info
                 orderby r.metric    
                 group r by r.metric into grp
                 select new { key = grp.Key, cnt = grp.Count()};

Ce résultat m'a donné un ensemble ordonné d'enregistrements avec des "métriques" et le nombre d'utilisateurs associés à chacun. Je suis clairement nouveau pour LINQ en général et pour mon œil inexpérimenté, cette approche semble très similaire à l'approche LINQ pure, mais m'a donné une réponse différente.

193
Gio

Après avoir appelé GroupBy, vous obtenez une série de groupes IEnumerable<Grouping>, où chaque groupe lui-même expose le Key utilisé pour créer le groupe et constitue également un IEnumerable<T> parmi les éléments présents. votre jeu de données d'origine. Vous devez simplement appeler Count() sur ce groupe pour obtenir le sous-total.

foreach(var line in data.GroupBy(info => info.metric)
                        .Select(group => new { 
                             Metric = group.Key, 
                             Count = group.Count() 
                        })
                        .OrderBy(x => x.Metric)
{
     Console.WriteLine("{0} {1}", line.Metric, line.Count);
}

C'était une réponse brillamment rapide, mais j'ai un problème avec la première ligne, en particulier "data.groupby (info => info.metric)"

Je suppose que vous avez déjà une liste/un tableau de quelque class qui ressemble à

class UserInfo {
    string name;
    int metric;
    ..etc..
} 
...
List<UserInfo> data = ..... ;

Quand vous faites data.GroupBy(x => x.metric), cela signifie "pour chaque élément x dans le IEnumerable défini par data, calculez que c'est .metric, puis regroupez tous les éléments de la même métrique dans un Grouping et retourne un IEnumerable de tous les groupes résultants.

    <DATA>           | Grouping Key (x=>x.metric) |
joe  1 01/01/2011 5  | 1
jane 0 01/02/2011 9  | 0
john 2 01/03/2011 0  | 2
jim  3 01/04/2011 1  | 3
jean 1 01/05/2011 3  | 1
jill 2 01/06/2011 5  | 2
jeb  0 01/07/2011 3  | 0
jenn 0 01/08/2011 7  | 0

il en résulterait le résultat suivant après le groupby:

(Group 1): [joe  1 01/01/2011 5, jean 1 01/05/2011 3]
(Group 0): [jane 0 01/02/2011 9, jeb  0 01/07/2011 3, jenn 0 01/08/2011 7]
(Group 2): [john 2 01/03/2011 0, jill 2 01/06/2011 5]
(Group 3): [jim  3 01/04/2011 1]
345
Jimmy

En supposant que userInfoList est un List<UserInfo>:

        var groups = userInfoList
            .GroupBy(n => n.metric)
            .Select(n => new
            {
                MetricName = n.Key,
                MetricCount = n.Count()
            }
            )
            .OrderBy(n => n.MetricName);

La fonction lambda pour GroupBy(), n => n.metric signifie qu'elle obtiendra le champ metric de chaque objet UserInfo rencontré. Le type de n dépend du contexte. Dans la première occurrence, il est de type UserInfo, car la liste contient des objets UserInfo. Dans la deuxième occurrence, n est de type Grouping, car il s'agit maintenant d'une liste d'objets Grouping.

Groupings ont des méthodes d'extension comme .Count(), .Key() et à peu près tout ce que vous pouvez attendre. Tout comme vous vérifieriez .Lenght sur un string, vous pouvez vérifier .Count() sur un groupe.

41
Vladislav Zorov
userInfos.GroupBy(userInfo => userInfo.metric)
        .OrderBy(group => group.Key)
        .Select(group => Tuple.Create(group.key, group.Count()));
20
DanielOfTaebl