关于C#:带groupby和count的linq

LINQ with groupby and count

这很简单,但我很困惑:给定这种类型的数据集:

1
UserInfo(name, metric, day, other_metric)

这个示例数据集:

1
2
3
4
5
6
7
8
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

我想检索一个按顺序(0,1,2,3..)列出度量的表,其中包含发生计数的总次数。所以从这一组中你会得到:

1
2
3
4
0 3    
1 2    
2 2    
3 1

我正在努力学习LINQ语法,但是我一直在想把groupby和count放在哪里……有什么帮助吗??

后期编辑:我永远无法得到已发布的答案,因为它们总是返回一条记录,其中包含不同的计数。但是,我能够将linq-to-sql示例组合在一起,这确实有效:

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

这个结果给了我一组有序的记录,其中包含"度量"和与每个记录关联的用户数。我显然对Linq是个新手,在我的未经训练的眼中,这种方法似乎与纯Linq方法非常相似,但给出了不同的答案。


在调用GroupBy之后,会得到一系列组IEnumerable,其中每个组本身都公开了用于创建组的Key,并且是原始数据集中所有项目的IEnumerable。你只需要打电话给Count()就可以得到小计。

1
2
3
4
5
6
7
8
9
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);
}


This was a brilliantly quick reply but I'm having a bit of an issue with the first line, specifically"data.groupby(info=>info.metric)"

我假设你已经有了一些class的列表/数组,看起来像

1
2
3
4
5
6
7
class UserInfo {
    string name;
    int metric;
    ..etc..
}
...
List<UserInfo> data = ..... ;

当您执行data.GroupBy(x => x.metric)时,它的意思是"对于data定义的IEnumerable中的每个元素x,计算它是.metric,然后将具有相同度量的所有元素分组到Grouping中,并返回所有结果组的IEnumerable。假设您的示例数据集

1
2
3
4
5
6
7
8
9
    <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

在groupby之后会产生以下结果:

1
2
3
4
(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]


假设userInfoListList

1
2
3
4
5
6
7
8
9
        var groups = userInfoList
            .GroupBy(n => n.metric)
            .Select(n => new
            {
                MetricName = n.Key,
                MetricCount = n.Count()
            }
            )
            .OrderBy(n => n.MetricName);

GroupBy()n => n.metric的lambda函数意味着它将从遇到的每个UserInfo对象中获取字段metricn的类型取决于上下文,在第一次出现时它是UserInfo类型,因为列表包含UserInfo对象。在第二次出现时,nGrouping类型,因为现在它是Grouping对象的列表。

Grouping有扩展方法,如.Count().Key()和您所期望的其他方法。就像你在string上检查.Lenght一样,你也可以在一个组上检查.Count()


1
2
3
userInfos.GroupBy(userInfo => userInfo.metric)
        .OrderBy(group => group.Key)
        .Select(group => Tuple.Create(group.key, group.Count()));