LINQ与groupby和count


220

这很简单,但我很茫然:鉴于这种数据集:

UserInfo(name, metric, day, other_metric)

和此示例数据集:

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 ..)列出指标,其中包含发生计数的总数。因此,从这个集合中您将得到:

0 3    
1 2    
2 2    
3 1

我正在努力使用LINQ语法,但是在哪里放置groupby并计数...有任何帮助吗?

开机自检编辑:我始终无法获得已发布的答案,因为它们总是返回一条记录,且记录的数目不同。但是我能够整理一个有效的LINQ to SQL示例:

        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方法非常相似,但是却给了我不同的答案。


是的,我有,但是吉米的解释为我提供了更多帮助。但是,我始终无法使他的榜样发挥作用,但这确实使我朝着新的方向发展。
Gio

@Jimmy使用LINQ表达式的功能语法而不是标准的LINQ查询语法,此外,他决定显示那些功能的立即执行,而不是延迟的执行格式。对于一个新人来说,这会令人困惑。不知道他为什么这样做。
理查德·罗伯逊

Answers:


393

调用之后GroupBy,您将获得一系列的组IEnumerable<Grouping>,其中每个分组本身都会公开Key用于创建组的组,并且也是IEnumerable<T>原始数据集中的任何项之一。您只需要调用Count()该分组即可获得小计。

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


这是一个非常出色的快速回复,但是我在第一行有一个问题,特别是“ data.groupby(info => info.metric)”

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

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

当您这样做时data.GroupBy(x => x.metric),它意味着“对于xIEnumerable中定义的每个元素,data,计算.metric,然后将具有相同度量的所有元素分组为a,Grouping然后返回IEnumerable所有结果组的an 。给定您的示例数据集

    <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之后将产生以下结果:

(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]

这是一个很棒的快速回复,但是我在第一行有一个问题,特别是“ data.groupby(info => info.metric)”。显然,“数据”是当前数据集,但是“ info.metric”会重新设置什么?类的定义?
Gio

“ info.metric”将是您在问题中提到的UserInfo类的度量标准属性/字段。
lee-m

1
感谢您弄清楚了,但实际上,这似乎给了我一个值-即不同指标计数的总数。在此示例中,我得到“指标4”,该指标向我指示我有多少个不同的计数。
Gio

1
哇。您完全解释了分组!仅此而已就值得发布....我仍然获得“ metrics 4”结果,但谢谢!
Gio

4
答案的开头,“在调用GroupBy之后,您将获得一系列的组IEnumerable <Grouping>,其中每个分组本身都会公开用于创建该组的键,并且也是原始数据中任何项目的IEnumerable <T> set”,这是LINQ Group的最清晰的解释。我尚未​​阅读,谢谢。
dumbledad

48

假设userInfoListList<UserInfo>

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

对于lambda表达式GroupBy()n => n.metric意味着它会得到场metric从每一个UserInfo遇到的对象。的类型n取决于上下文,在第一次出现时,其类型是UserInfo,因为列表包含UserInfo对象。在第二个实例nGrouping,它的类型为,因为现在它是一个Grouping对象列表。

Grouping具有扩展方法,如.Count().Key()以及您期望的几乎所有其他方法。正如你查.Lenght一个string,你可以检查.Count()在一组。


23
userInfos.GroupBy(userInfo => userInfo.metric)
        .OrderBy(group => group.Key)
        .Select(group => Tuple.Create(group.Key, group.Count()));

1
小错字-> group.keySelect(...)中的错字必须是group.Key
1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.