数据表按分组求和

3

在队列中,我有以下格式的数据表格:

some table in the Queue
    Name Rank
    AAA  9 
    BBB  5
    CCC  1
    DDD  5

some other table in the Queue
    Name Rank
    AAA  1 
    SSS  5
    MMM  1
    DDD  8

使用LINQ需要连续处理表格,并按照以下格式将结果添加到全局DataTable中:

Name  Rank1  Rank2  Rank3  Rank>3
AAA   1      0      0      1
BBB   0      0      0      1
CCC   1      0      0      0
DDD   0      0      0      2
SSS   0      0      0      1
MMM   0      0      0      0

在全局表中,有4个列用于记录一个名字在排名1、2、3或>3的次数。
现在如果这个名字已经存在于全局表中,我不会添加它,而只会递增排名计数列,如果不存在,则添加。
我用嵌套循环做到了这一点,但我想知道是否有人可以帮我使用LINQ语法做到这一点,另外,使用LINQ会比嵌套循环更快吗?
请注意,新的表每秒钟都会添加到队列中,我将从队列中获取某个表并将其处理到全局数据表中。
1个回答

4
table1.AsEnumerable().Concat(table2.AsEnumerable())
      .GroupBy(r => r.Field<string>("Name"))
      .Select(g => new {
          Name = g.Key,
          Rank1 = g.Count(x => x.Field<int>("Rank") == 1),
          Rank2 = g.Count(x => x.Field<int>("Rank") == 2),
          Rank3 = g.Count(x => x.Field<int>("Rank") == 3),
          OtherRank = g.Count(x => x.Field<int>("Rank") > 3)
      }).CopyToDataTable();

你需要实现CopyToDataTable方法,其中泛型类型T不是DataRow。一个经过优化的解决方案(单次解析和单次循环组排名):
(from row in table1.AsEnumerable().Concat(table2.AsEnumerable())
 group row by row.Field<string>("Name") into g
 let ranks = g.Select(x => x.Field<int>("Rank")).ToList()
 select new {
    Name = g.Key,
    Rank1 = ranks.Count(r => r == 1),
    Rank2 = ranks.Count(r => r == 2),
    Rank3 = ranks.Count(r => r == 3),
    OtherRank = ranks.Count(r => r > 3)        
 }).CopyToDataTable();

但是如果名称已经存在,这会增加排名吗? - user1590636
@user1590636 不是的,如果名称在两个表中都存在,则每个组“g”将有两行。然后,“ranks”将有两个值。例如,对于“AAA”组,将有值“1”和“9”。计算计数将产生“Rank1 = 1,Rank2 = 0,Rank3 = 0,OtherRank = 1”。 - Sergey Berezovskiy
@user1590636 没问题 :) Linq 是个很棒的东西 - Sergey Berezovskiy
但为什么他们不将CopyToDataTable作为内置功能,至少对于Enumerable类型呢? - user1590636
1
@user1590636,我同意你的观点,那个东西应该内置在系统中。不知道为什么它只存在于 MSDN 文章中。 - Sergey Berezovskiy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接