2010-02-10 22 views
6

Ecco il programma di installazione:utilizzando LINQ e C#, cercando di ottenere due liste da un elenco di elementi maestri raggruppati per due liste interne

public class Parent 
{ 
    public List<Child> ChildrenA = new List<Child>(); 
    public List<Child> ChildrenB = new List<Child>(); 
} 

public class Child 
{ 
    public Child (string name) {Name=name;} 
    public string Name {get;set;} 
} 

Avere i seguenti dati:

var parents = new List<Parent>(); 
parents.Add (new Parent()); 
parents[0].ChildrenA.Add (new Child("A1")); 
parents[0].ChildrenA.Add (new Child("A2")); 
parents[0].ChildrenB.Add (new Child("B1")); 
parents.Add (new Parent()); 
parents[1].ChildrenA.Add (new Child("A3")); 

Ora io' m cercando di ottenere il seguente risultato nella dichiarazione ONE LINQ:

var result = ... // would be an anonymous type 

Assert.That (result.ChildrenA.Count, Is.EqualTo(3)); 
Assert.That (result.ChildrenA[0].Name, Is.EqualTo("A1")); 
Assert.That (result.ChildrenA[1].Name, Is.EqualTo("A2")); 
Assert.That (result.ChildrenA[2].Name, Is.EqualTo("A3")); 

Assert.That (result.ChildrenB.Count, Is.EqualTo(1)); 
Assert.That (result.ChildrenB[0].Name, Is.EqualTo("B1")); 

ho provato raggruppamento, utilizzando SelectMany, si unisce e mi ca non sembra trovare il modo corretto.

Qualsiasi mago Linq in giro?

PS: Inoltre, voglio attraversare l'elenco principale solo una volta ...;)

risposta

3
var result = parents.Aggregate(
        new 
        { 
         ChildrenA = Enumerable.Empty<Child>(), 
         ChildrenB = Enumerable.Empty<Child>() 
        }, 
        (a, p) => new 
           { 
            ChildrenA = a.ChildrenA.Concat(p.ChildrenA), 
            ChildrenB = a.ChildrenB.Concat(p.ChildrenB) 
           }); 

questo è fondamentalmente equivalente a:

var result = new 
      { 
       ChildrenA = Enumerable.Empty<Child>() 
             .Concat(parents[0].ChildrenA) 
             .Concat(parents[1].ChildrenA) 
             .Concat(parents[2].ChildrenA) 
             ..., 

       ChildrenB = Enumerable.Empty<Child>() 
             .Concat(parents[0].ChildrenB) 
             .Concat(parents[1].ChildrenB) 
             .Concat(parents[2].ChildrenB) 
             ... 
      }; 

E 'probabilmente più efficiente utilizzare un POFL (pianura vecchio ciclo foreach):

var childrenA = new List<Child>(); 
var childrenB = new List<Child>(); 

foreach (var parent in parents) 
{ 
    childrenA.AddRange(parent.ChildrenA); 
    childrenB.AddRange(parent.ChildrenB); 
} 

var result = new 
      { 
       ChildrenA = childrenA, 
       ChildrenB = childrenB 
      }; 
+0

Inter esting ... Non so perché funzioni e se è ottimale ... –

+0

Ho paura dell'esecuzione di Concat su una lista contenente diverse centinaia di elementi ... Hai ragione che forse dovrei semplicemente usare un ciclo foreach. –