GroupBy使用LINQ,但在另一列上不同,并且仍然可以计算其他记录

时间:2017-01-04 18:07:36

标签: linq c#-4.0

当存在类似于以下内容的对象时,如何使用LINQ基于Id运行GroupBy:

public class foo
{
    public int id { get; set; }
    public string name { get; set; }  
    public string lang { get; set; }  
    public int displayOrder { get; set; } 
    public int count { get; set; } 

}

列表可能是:

 id = 1, name="test1", lang = "en", displayOrder = 1, count = 1
 id = 1, name="test2", lang = "fr", displayOrder = 2, count = 2
 id = 1, name="test3", lang = "de", displayOrder = 3, count = 1
 id = 2, name="test4", lang = "en", displayOrder = 2, count = 1
 id = 2, name="test5", lang = "fr", displayOrder = 3, count = 1
 id = 3, name="test6", lang = "en", displayOrder = 6, count = 1
 id = 3, name="test7", lang = "fr", displayOrder = 4, count = 1
 id = 4, name="test8", lang = "en", displayOrder = 5, count = 1
 id = 5, name="test9", lang = "de", displayOrder = 6, count = 1

我想运行LINQ以使其按分组依据值,但应根据lang过滤不同的id值,例如: “fr”,如果“fr”中没有任何内容,它应该只输出“en”的默认语言记录  但是还应该根据Id计算记录总数,它应该检索上面的以下结果:

 id = 1, name="test2", lang = "fr", displayOrder = 2, count = 4
 id = 2, name="test5", lang = "fr", displayOrder = 3, count = 2
 id = 3, name="test7", lang = "fr", displayOrder = 4, count = 2
 id = 4, name="test8", lang = "en", displayOrder = 5, count = 1
 id = 5, name="test9", lang = "de", displayOrder = 6, count = 1

拜托,有没有办法用LINQ做这样的事情? 你们所有的LINQ专家,我理想地使用lambda寻找查询,这将是一个很大的帮助。提前谢谢。

2 个答案:

答案 0 :(得分:2)

您可以将目标语言排在前面,然后选择组中的第一项:

var query = from f in foos
            group f by f.id into g
            let lang = (from f in g
                        orderby 
                          f.lang == "fr" ? 0 : 1,
                          f.lang == "en" ? 0 : 1,
                          f.lang
                         select f).First()
            select new 
            {
              id = g.Key,
              lang.name,
              lang.lang,
              lang.displayOrder,
              count = g.Sum(f => f.count)
            };

这假设对(id,lang)是唯一的。

Demo.

答案 1 :(得分:0)

这可能会稍快一些,因为它不需要遍历组中的所有项目进行订购。

var res = data
    .GroupBy(d => d.id)
    .Select(g => new {
        id = g.Key,
        count = g.Sum(d => d.count),
        Lang = g.FirstOrDefault(d => d.lang == "fr") ?? g.First()
    })
    .Select(g => new {
        g.id,
        g.Lang.lang,
        g.Lang.name,
        g.Lang.displayOrder,
        g.count
    })
    .ToList();