2010-08-12 25 views
6

Me gustaría ordenar una colección basada en una propiedad de subcolección.Cómo ordenar una colección basada en una propiedad de subcolección

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

A continuación sólo para el propósito de prueba, estoy preparando mi colección de persona con salarios colecciones internas de cada uno:

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

Ahora queremos ordenar la recogida de la gente, pero el uso de su colección SalaryValue interior como parámetro.

¿Cómo puedo ordenar la lista pero usando expresiones LINQ/Lambda en la colección interna de Salaries?

por lo que tendría:

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

el código de inicialización carece de campo de lista de sueldos para una persona (personas [i]) –

Respuesta

8

Para mí, que se parece a:

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

Tenga en cuenta que usted no está realmente determinan un conjunto de personas - estás ordenar una colección de (persona, salario), que es lo que hace el efecto de aplanamiento de tener dos cláusulas from.

(Lo anterior no proporcionará exactamente la misma salida, pero una vez que tienes la persona y su salario, se puede conseguir en los otros valores.)

+0

Este tipo de salario, independiente de la colección externa. Es ambiguo si al aficionado le importa si la lista contiene 'Johanna: 30000, Junior: 70000, Johanna: 75000, Junior: 80000' o si quiere que sea' Johanna: 30000, Johanna: 75000, Junior: 70000, Junior: 80000 ' – Marc

+0

@Marc: Eso es cierto ... pero como ha sido aceptado, asumo que esto es lo que se quería. –

+0

¿No debería 'Writeline()' estar un poco más elaborado que solo contener el 'par'? –

2

Parece que la lógica de Jon es correcta, pero el código de muestra no coincide con los OP's. Probablemente debería ser de la misma familia:

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

Gracias, he arreglado mi cláusula orderby. No he cambiado la proyección. Supongo que una vez que tienes la persona y el salario, puedes imprimir los bits que quieras y dejar el resto. –

+0

Ambos comentarios fueron geniales, gracias chicos –

+0

@Jon: Gracias por soportar mi nitpicking. :-) –

Cuestiones relacionadas