LINQ Multiple Group By in List <t>然后转换为List <t>

时间:2018-06-01 07:43:17

标签: c# .net linq

我有以下课程

public class Person
{
  public string ID {get; set;}
  public string Name {get; set;}
  public string District {get; set;}
  public string Level {get; set;}
}

然后在我的函数上,我正在编写一个LINQ来将Person列表按区域分组,然后按Level分组到同一类型的新列表(Person)

我想以一种不会使用var(使其成为匿名类型)和新的方式编写它:

这样的东西
List<Person> persons; \\this already has values
List<Person> grpByP = persons
  .GroupBy()
  .ToList<Person>(); \\ Linq query to group persons list by District and Level

我只是不知道如何编写grpByP LINQ查询。

UPDATE :我希望ID和名称保留在grpByP变量的值中,因为使用匿名类型只会包含区和级别。

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

这听起来像你只想按地区,然后按级别订购你的清单。这很容易

List<Person> result = persons.OrderBy(p => p.District).ThenBy(p => p.Level).ToList();

答案 1 :(得分:2)

我认为你是在追求这样的事情......

List<Person> persons = new List<Person>
{
    new Person()
    {
        ID = "1",
        Name = "Joe",
        District = "Columbia",
        Level = "10"
    },
    new Person()
    {
        ID = "2",
        Name = "Beth",
        District = "Columbia",
        Level = "10"
    },
    new Person()
    {
        ID = "3",
        Name = "Jim",
        District = "Washington",
        Level = "11"
    }
};  //this already has values
var grpByP = persons
    .GroupBy(p => new { p.District, p.Level })
    .Select(g => new
    {
        g.Key,
        People = g.ToList<Person>()
    });

foreach (var g in grpByP)
{
    Console.WriteLine("Group:");
    Console.WriteLine(g.Key.District);
    Console.WriteLine(g.Key.Level);
    Console.WriteLine("People:");
    foreach (Person p in g.People)
        Console.WriteLine(p.Name);
    Console.WriteLine();
}
Console.ReadLine();

输出: -

  

组:   哥伦比亚10   人:   乔   贝丝

     

组:   华盛顿11   人:   吉姆

答案 2 :(得分:0)

The question for which this one had been originally marked as duplicate已经解释了如何使用GroupBy。我将解决第二部分:“转换为List<Person>”和“不使用var”。

首先,关于将GroupBy的结果转换为List<Person>:您不能这样做。 GroupBy操作的结果是IEnumerable<IGrouping<String,Person>>(假设您按string属性进行分组),其本身是IEnumerable IEnumerable<Person>;这些内部IEnumerable<Person>中的每一个对应于找到的每个键,您可以使用Key属性检查每个案例的键:

var grouped = persons.GroupBy(p => p.District);
foreach(var group in grouped) 
{
    Console.WriteLine($"People in disctrict {group.Key}:");
    foreach(var person in group)
    {
        Console.WriteLine(person.Name);
    }
}

可以回去获取未分组人员的完整列表,但我认为这没有多大意义:

var ungrouped = grouped.SelectMany(g => g).ToList<Person>();

关于不使用var:您当然可以将变量定义为IEnumerable<IGrouping<String,Person>>,但我不知道这样做会带来什么好处。

修改:如果其他答案显示您实际想要做的是排序您的数据,而不是 group <,则所有这些都不适用/ em>它。

根据您的评论

修改“我希望ID和名称保留在grpByP变量的值中,因为使用匿名类型只会包含区域和级别 “ - GroupBy不会创建匿名对象,它会保留您提供的原始对象(请参阅上面的示例)。只有在结果组中执行.Select(p => new {p.Discrict})之类的操作时,才会创建匿名对象。