【问题标题】:How to sort a collection based on a subcollection property如何根据子集合属性对集合进行排序
【发布时间】:2011-03-29 03:31:47
【问题描述】:

我想根据子集合属性对集合进行排序。

//the subcollection
public class Salary
{
   public int SalaryId {get;set;}
   public int SalaryYear {get;set;}
   public double SalaryValue {get;set;} //this is the field we want to sort the parent collection "Person"
}

//the main collection
public class Person
{
   public int PersonId {get;set;}
   public string PersonName {get;set;}
   public List<Salary> Salaries {get;set;}
}

下面只是为了测试目的,我正在准备我的人的集合,每个人都有 Salaries 内部集合:

List<Person> people = new List<Person>();
//add two salaries for Junior
people.Add(new Person { PersonId = 1, PersonName = "Junior" });
people[0].Salaries.Add(new Salary { SalaryId=1, SalaryYear=2011, SalaryValue=80000 });
people[0].Salaries.Add(new Salary { SalaryId=2, SalaryYear=2010, SalaryValue=70000 });

//add two salaries for Johanna
people.Add(new Person { PersonId = 2, PersonName = "Johanna" });
people[0].Salaries.Add(new Salary { SalaryId=3, SalaryYear=2011, SalaryValue=40000 });
people[0].Salaries.Add(new Salary { SalaryId=4, SalaryYear=2010, SalaryValue=30000 });

现在我们要对人员集合进行排序,但使用他们的内部集合 SalaryValue 作为参数。

如何在 Salaries 内部集合中使用 LINQ / Lambda 表达式对列表进行排序?

所以我会:

PersonName: Johanna, SalaryValue=30000, SalaryYear=2010
PersonName: Johanna, SalaryValue=40000, SalaryYear=2011
PersonName: Junior, SalaryValue=70000, SalaryYear=2010
PersonName: Junior, SalaryValue=80000, SalaryYear=2011

【问题讨论】:

  • 代码缺少一个人(people[i])的薪水列表字段的初始化

标签: linq sorting c#-3.0 lambda sql-order-by


【解决方案1】:

对我来说,这看起来像:

var query = from person in people
            from salary in person.Salaries
            orderby salary.SalaryValue
            select new { person, salary };

foreach (var pair in query)
{
    Console.WriteLine(pair);
}

请注意,您并没有真正对 people 的集合进行排序 - 您正在对 (person, Salary) 的集合进行排序,这就是拥有两个 from 子句的扁平化效果所做的.

(上面不会提供完全相同的输出,但是一旦你得到了这个人和他们的薪水,你就可以得到其他值。)

【讨论】:

  • 按薪水排序,独立于外部集合。如果发布者关心列表是否包含Johanna:30000, Junior:70000, Johanna:75000, Junior:80000 或者他是否希望它是Johanna:30000, Johanna:75000, Junior:70000, Junior:80000,这是模棱两可的
  • @Marc:确实如此……但既然它已被接受,我认为这就是我们想要的。
  • 不应该Writeline() 比只包含pair 更详细吗?
  • @GennadyVanin--新西伯利亚:为什么?至少可以用于诊断目的。
  • 您应该关注advise by @Steven Sudit 更改为select new { person.PersonName, salary.SalaryValue};。您的 WriteLine(pair) 打印重复行的行:{person = NameSpaceName.Person, salary = NameSpaceName.Salary}。所以,正确的答案是零赞成票,而你的“诊断”一票是 +4
【解决方案2】:

看起来 Jon 的逻辑是正确的,但示例代码与 OP 的不匹配。应该更像这样:

var query = from person in people
            from salary in person.Salaries
            orderby salary.SalaryValue
            select new { person.PersonName, salary.SalaryValue, salary.SalaryYear };

foreach (var tuple in query)
{
    Console.WriteLine(tuple);
}

【讨论】:

  • 谢谢,我已经修复了我的 orderby 子句。我没有改变投影——我想一旦你得到了人和薪水,你可以打印任何你想要的东西,然后留下剩下的。
  • @Jon:感谢您忍受我的吹毛求疵。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
相关资源
最近更新 更多