2016-04-21 10 views
1

Mit einer Liste von Typ A, die jeweils eine Liste von Typ B enthalten, was ist der beste Weg, um eine Liste aller Typ B zu erhalten, die jeweils eine Liste des Typs A enthalten, zu dem sie gehören?Invertierte verschachtelte Kollektionen in LINQ

Nachdem eine Liste wie folgt aus:

var parents = new List<Parent> { 
    { 
     new Parent { 
      ID = 1, 
      Childs = new List<Child> { 
       { 
        new Child { 
         ID = 1 
        } 
       }, 
       { 
        new Child { 
         ID = 2 
        } 
       }, 
       { 
        new Child { 
         ID = 3 
        } 
       } 
      } 
     }      
    }, 
    { 
     new Parent { 
      ID = 2, 
      Childs = new List<Child> { 
       { 
        new Child { 
         ID = 3 
        } 
       }, 
       { 
        new Child { 
         ID = 4 
        } 
       }, 
       { 
        new Child { 
         ID = 5 
        } 
       } 
      } 
     }      
    } 
}; 

Ich mag diese Abfrage das folgende Ergebnis zu erhalten:

[ 
    { 
    Child = 1, 
    InParent = [1] 
    }, 
    { 
    Child = 2, 
    InParent = [1] 
    }, 
    { 
    Child = 3, 
    InParent = [1, 2] 
    }, 
    { 
    Child = 4, 
    InParent = [2] 
    }, 
    { 
    Child = 5, 
    InParent = [2] 
    }, 
] 

EDIT: habe ich versucht, einen Ansatz, um den Childs abzuflachen ersten mit & Distinct, aber nicht sicher, wie Sie dies wieder mit dem übergeordneten verknüpfen:

var foo = 
    from childId in parents.SelectMany(x => x.Childs).Select(x => x.ID).Distinct() 
    select 
     new 
     { 
      childId = childId, 
      inParent = // Missing Part 
     }; 
+2

Haben Sie schon etwas probiert, bevor Sie eine Frage gestellt haben? Was ist dein Problem? – wudzik

+0

Sicher, ich habe versucht, die Kinder mit SelectMany/Distinct zu glätten, die die eindeutige Liste aller beteiligten Kinder zurückgibt, aber ohne Verbindung zu dem Elternteil, wo sie gehörten. Natürlich könnte ich mit Schleifen durchlaufen, meine Frage ist, wie dies in einer LINQ-Abfrage zu erreichen. –

Antwort

4

Sie haben zu verwenden SelectMany zuerst um sie zu glätten, dann GroupBy zur Gruppe verwenden von Kind-ID und String.Join jede Eltern-ID zu verketten:

var childParents = parents 
    .SelectMany(p => p.Childs.Select(c => new {Parent = p, Child = c})) 
    .GroupBy(x => x.Child.ID) 
    .Select(g => new 
    { 
     Child = g.Key, 
     InParent = String.Join(", ", g.Select(x => x.Parent.ID)) 
    }); 

Ergebnis:

enter image description here

Wenn Sie nicht möchten, dass die Eigenschaft InParent eine Zeichenfolge ist, sondern eine List<int> (oder ein Array), verwenden Sie Folgendes:

..... 
InParent = g.Select(x => x.Parent.ID).ToList() // or ToArray() 
0

Sie können Ihr großes Problem in zwei einfachere Probleme aufgeteilt:

  1. Ein anonymes Objekt für jedes Eltern/Kind-Paar, einen Verweis auf die Eltern als auch für das Kind enthält. Sie können eine einfache LINQ-Abfrage mit zwei from Klauseln dafür verwenden.

  2. Gruppieren Sie diese Objekte in die Darstellung, die Sie benötigen. Die group by Klausel ist dein Freund hier.

-1

Ich denke, Sie sollten versuchen, Ihr Datenmodell ändern, wenn Sie zum Speichern Baum wie Struktur suchen, in diesem Szenario, das Sie immer einzelne verlinkte Liste mit benutzerdefinierten Objekt & verschachtelte Verweis auf entsprechende Eltern/Kind in ähnlicher verwenden sollten So speichern Sie in der Datenbank.

Es ist eine ideale Möglichkeit, Datenstrukturen solcher Art zu behandeln, da Sie sonst in vielen verschachtelten Abfragen landen.