2009-06-22 22 views
28

Tener las siguientes clases (muy simplificado):LINQ: ¿Cómo obtener elementos de una lista interna en una lista?

public class Child 
{ 
    public string Label; 
    public int CategoryNumber; 
    public int StorageId; 
} 

public class Parent 
{ 
    public string Label; 
    public List<Child> Children = new List<Child>(); 
} 

Y con los siguientes datos:

var parents = new List<Parent>(); 

var parent = new Parent() {Label="P1"}; 
parent.Children.Add(new Child() {Label="C1", CategoryNumber=1, StorageId=10}); 
parent.Children.Add(new Child() {Label="C2", CategoryNumber=2, StorageId=20}); 
parents.Add(parent); 

parent = new Parent() {Label="P2"}; 
parent.Children.Add(new Child() {Label="C3", CategoryNumber=1, StorageId=10}); 
parent.Children.Add(new Child() {Label="C4", CategoryNumber=2, StorageId=30}); 
parents.Add(parent); 

parent = new Parent() {Label="P3"}; 
parent.Children.Add(new Child() {Label="C5", CategoryNumber=3, StorageId=10}); 
parent.Children.Add(new Child() {Label="C6", CategoryNumber=2, StorageId=40}); 
parents.Add(parent); 

Ahora, ¿cómo iba a obtener una lista de los niños (con CategoryNumber = 2) de la lista de padres que contienen al menos un hijo con CategoryNumber = 1?

que puede hacer lo siguiente, pero no parece ser óptimo:

var validParents = from p in parents 
        where p.Children.Any (c => c.CategoryNumber==1) 
        select p; 
var selectedChildren = validParents.Select(p => from c in p.Children 
               where c.CategoryNumber == 2 
               select c); 

Esto es lo que me pasa por selectedChildren:

  • IEnumerable<IEnumerable<Child>>
    • IEnumerable<Child>
      • C2 2 20
    • IEnumerable<Child>
      • C4 2 30

¿Es posible sólo tienen una lista plana que contiene los elementos de dos niños en vez de dos sub-lista? ¿Cómo se traduciría en LINQ?

Respuesta

33

Scott La respuesta es genial; Sólo me gustaría señalar que se puede hacer, de hecho, esta consulta utilizando la sintaxis de consulta continuación:

from parent in parents 
where parent.Children.Any (c => c.CategoryNumber==1) 
select parent into p 
from child in p.Children 
where child.CategoryNumber == 2 
select child 

Observe cómo el "en" que permite canalizar el resultado de una consulta en la siguiente consulta . Bastante astuto, ¿eh?

+1

@Eric: Sí, la sintaxis de la consulta LINQ para esto es bastante buena (y probablemente un poco mejor para usarla que para mezclar la sintaxis del método de consulta y extensión). Sin embargo, cada vez que encuentro este tema, siento que a LINQ le falta un operador de concatenación (similar a Seq.concat en F #), que podría usarse como alternativa a SelectMany, y de hecho es muy útil en otros casos. Una sobrecarga sencilla del método Enumerable.Concat que toma un parámetro IEnumerable > haría bastante bien el trabajo. ¿Alguna idea (o incluso mejor, planes) con respecto a esto? – Noldorin

+0

Ah, parece que MoreLINQ define este operador: http://code.google.com/p/morelinq/wiki/OperatorsOverview. Sin embargo, sería bastante bueno tener en el BCL (junto con algunos otros como Zip). – Noldorin

+0

gracias ... me salvaste el día – thiagolsilva

41

Puede enlazar un par de consultas juntas, usando SelectMany y Where.

var selectedChildren = (from p in parents 
         where p.Children.Any (c => c.CategoryNumber==1) 
         select p) 
         .SelectMany(p => p.Children) 
         .Where(c => c.CategoryNumber == 2); 

// or... 

var selectedChildren = parents 
         .Where(p => p.Children.Any(c => c.CategoryNumber == 1)) 
         .SelectMany(p => p.Children) 
         .Where(c => c.CategoryNumber == 2); 
+0

Funciona muy bien! SelectMany parece ser un método útil. ¿Tiene alguna sugerencia para un sitio web o un libro sobre la comprensión completa de Linq? –

+0

Para los sitios, en el que se encuentra es bueno, la mayoría de mis problemas de linq se han resuelto con una búsqueda rápida o una pregunta publicada aquí. el único libro que he visto es este ... http://www.amazon.com/Programming-Microsoft%C2%AE-PRO-Developer-Paolo-Pialorsi/dp/0735624003/ref=sr_1_23?ie = UTF8 & s = books & qid = 1245694305 & sr = 8-23 –

+0

¡Gracias por proporcionar más de una sintaxis! – Peter

Cuestiones relacionadas