2011-09-29 22 views
6

bir düzleştirilmiş ebeveyn-çocuk ilişkileri içeren bir numaralandırılabilir listesi vardır: bir List<Child> özelliği içeren bir çocuk sınıfı ve Ana sınıfı tanımladıkLinq çıkıntı

ParentGuid1, ParentName1, ChildGuid1, ChildName1 
ParentGuid1, ParentName1, ChildGuid2, ChildName2 
ParentGuid2, ParentName2, ChildGuid3, ChildName3 
ParentGuid2, ParentName2, ChildGuid4, ChildName4 

Çocuklar denir.

Benzersiz üstyapı başına bir Ana sınıfın bir örneğiyle nesne grafiğinde oluşturmak için linq'i kullanabilirim, bu üst öğeyle ilişkilendirilmiş çocuklar tarafından doldurulmuş bir Listeye başvuruda bulunabilir.

(bu kod derleme değil notu) bu çizgisinde

şey:

myFlattenedHierarchy.Select(p => new Parent 
    {Guid = p.ParentGuid, 
    Name = p.ParentName, 
    Children = myFlattenedHierarchy.Where(c => c.ParentGuid == p.ParentGuid).Select(c => new Child{Guid = c.ChildGuid, Name = c.ChildName}) 
    }); 
+0

Bu grafik yalnızca 2 seviyeli derin, yani 'Döngü 1- * Çocuk 'döngüleri olmadan mı? Veya GUID'in global ve her bir "ChildGuid" bir "ParentGuid" olabilir mi? – user7116

cevap

5
myFlattenedHierarchy.Select(p => new Parent 
    {Guid = p.ParentGuid, 
    Name = p.ParentName, 
    Children = myFlattenedHierarchy.Where(c => c.ParentGuid == p.ParentGuid).Select(c => new Child{Guid = c.ChildGuid, Name = c.ChildName}) 
    }); 

Bunu yapmak gerekir, ancak Children bir listesi olamaz, bu IEnumerable olmak zorunda.

2

Sana GroupBy() (tam açıklama: derlenmiş değil): kullanabilirsiniz inanıyoruz

myFlattenedHierarchy.GroupBy(row => row.ParentGuid) 
    .Select(group => new Parent 
     { 
      Guid = group.Key.ParentGuid, 
      Name = group.Key.ParentName, 
      Children = myFlattenedHierarchy.Where(c => c.ParentGuid == group.Key.ParentGuid) 
       .Select(c => new Child{ Guid = c.ChildGuid, Name = c.ChildName }) 
       .ToList() 
     }); 
0

Düz koleksiyonunuzda bir döngü varsa, özyinelemeli ve sonsuz özyinelemeyle başa çıkmanız gerekir. Linq tam sorun için kullanılamaz, ancak belirli bir düğümün çocuğunu geri döndürmeye yardımcı olabilir.

3

Basit bir döngü ile bunu yapmanın ön Linq yolu.

Dictionary<Guid, Parent> parents = new Dictionary<Guid, Parent>(); 
foreach(RowType row in myFlattenedHierarchy) //just enumerate once 
{ 
    if (!parents.ContainsKey(row.ParentGuid) 
    { 
    Parent newParent = new Parent(row); 
    parents[row.ParentGuid] = newParent; 
    } 

    Child newChild = new Child(row); 

    Parent theParent = parents[row.ParentGuid]; 
    theParent.Children.Add(newChild); 
} 

List<Parent> result = parents.Values.ToList(); 

Yoksa benzer bir sonuç almak için GroupBy kullanabilirsiniz.

from row in myFlattenedHierarchy 
group row by row.ParentGuid into g 
select new Parent() 
{ 
    Guid = g.Key, 
    Name = g.First().ParentName, 
    Children = 
    (
    from childRow in g 
    select new Child() 
    { 
     Guid = childrow.ChildGuid, 
     Name = childrow.ChildName 
    } 
).ToList() 
} 

Daha fazla bakım gerektiren bir toss-up. Her iki durumda da, myFlattenedHierarchy'i döngü/sorgu içinde yeniden numaralandırmayın.

+0

Sanırım ikinci örneğiniz biraz değiştirilmeye ihtiyaç duyuyor, 'ParentGuid' & 'ParentName' satırın özellikleri değil mi, yoksa bir şey mi eksik? –

+0

@DogEars evet, satır benim kullandığım yerde değildi - yerine g kullanmak için düzenlenmiş. ParentGuid ve ParentName bu düzleştirilmiş bir Hiyerarşi (her satırda üst ve alt bilgi) olduğu gibi orada. –

+0

Bu linq sorgusunda bana yardımcı olabilir misiniz: http: //stackoverflow.com/questions/38120664/how-to-group-by-on-2-child-entities-and-get-total-of-both-this -çocuk-varlıklar –

0

Bu, David B'nin ikinci örneğine çok benzemeli, ancak biraz düzeltme yapmadan çalışmasını sağlayamadım (birden çok sütuna göre gruplama) böylece kaydı için buraya ekledim.

from row in myFlattenedHierarchy 
group row by new { row.ParentGuid, row.ParentName } into g 
select new Parent() 
{ 
    Guid = g.Key.ParentGuid, 
    Name = g.Key.ParentName, 
    Children = 
    (
    from childRow in g 
    select new Child() 
    { 
     Guid = childRow.ChildGuid, 
     Name = childRow.ChildName 
    } 
).ToList() 
};