it-swarm-pt.tech

LINQ com groupby e count

Isso é bem simples, mas estou perdido: dado esse tipo de conjunto de dados:

UserInfo(name, metric, day, other_metric)

e este conjunto de dados de amostra:

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

Gostaria de recuperar uma tabela que lista métricas em ordem (0,1,2,3 ..) com o número total de vezes que a contagem ocorre. Então, a partir desse set você acabaria com:

0 3    
1 2    
2 2    
3 1

Eu estou lutando com a sintaxe LINQ, mas estou preso em onde colocar um groupby e contar .... qualquer ajuda?

POST Edit: Nunca consegui que as respostas postadas funcionassem, pois elas sempre retornavam um registro com o número de contagens diferentes. No entanto, consegui reunir um exemplo de LINQ to SQL que funcionou:

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

Esse resultado me deu um conjunto ordenado de registros com "métricas" e o número de usuários associados a cada um deles. Eu sou claramente novo no LINQ em geral e, para meu olho destreinado, essa abordagem parece muito semelhante à abordagem LINQ pura, mas me deu uma resposta diferente.

185
Gio

Depois de chamar GroupBy, você obtém uma série de grupos IEnumerable<Grouping>, onde cada Agrupamento em si expõe o Key usado para criar o grupo e também é um IEnumerable<T> de quaisquer itens no seu conjunto de dados original. Você só precisa chamar Count() naquele Agrupamento para obter o subtotal.

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);
}

Esta foi uma resposta rápida e rápida, mas estou tendo um problema com a primeira linha, especificamente "data.groupby (info => info.metric)"

Eu estou supondo que você já tem uma lista/array de algum class que se parece com

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

Quando você faz data.GroupBy(x => x.metric), significa "para cada elemento x no IEnumerable definido por data, calcule o .metric, agrupe todos os elementos com a mesma métrica em um Grouping e retorne um IEnumerable de todos os grupos resultantes. do

    <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

resultaria no seguinte resultado após o 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]
339
Jimmy

Assumindo que userInfoList é um List<UserInfo>:

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

A função lambda para GroupBy(), n => n.metric significa que obterá o campo metric de cada objeto UserInfo encontrado. O tipo de n depende do contexto, na primeira ocorrência é do tipo UserInfo, porque a lista contém os objetos UserInfo. Na segunda ocorrência, n é do tipo Grouping, porque agora é uma lista de objetos Grouping.

Groupings tem métodos de extensão como .Count(), .Key() e praticamente qualquer outra coisa que você esperaria. Assim como você veria .Lenght em um string, você pode verificar .Count() em um grupo.

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