2013-11-15 19 views
6

hiyerarşik kümesi döndürmek içinLINQ özyinelemeli sorgu aşağıdaki modellerin listesi verildiğinde grupların

public class Team 
{ 
    public int TeamId { get; set; } 
    public int ParentTeamId { get; set; } 
} 

Bu

gibi görünen bir hiyerarşi almak için beni sağlayacak bir özyinelemeli linq sorgusu yazmaya çalışıyorum
Team 
    ChildTeams 
Team 
    Team 
     ChildTeams 

Birçok yaklaşımı denedim ve birçok benzer soru gördüm, ancak bunların hiçbiri özellikle sorunu çözmeme yardımcı oldu.

private class TeamGrouping 
{ 
    public int? ParentTeamId { get; set; } 
    public IEnumerable<Team> ChildTeams { get; set; } 
    public IEnumerable<TeamGrouping> Grouping { get; set; } 
} 

private IEnumerable<TeamGrouping> ToGrouping(IEnumerable<Team> teams) 
{ 
    return teams.GroupBy(t => t.ParentTeamId, (parentTeam, childTeams) => new TeamGrouping {ParentTeamId = parentTeam, ChildTeams = childTeams}); 
} 

private IEnumerable<TeamGrouping> ToGrouping(IEnumerable<TeamGrouping> teams) 
{ 
    return teams.GroupBy(t => t.ParentTeamId, (parentTeam, childTeams) => new TeamGrouping{ParentTeamId = parentTeam, Grouping = childTeams}); 
} 

ben ToGrouping(IEnumerable<TeamGrouping>) içine ilk ToGrouping(IEnumerable<Team>) ve ardından sonraki dönen gruba takımların listesini geçerdi ama bu yanlış sonuçlar üretiyor: Denedim son girişim bu doğrultuda gitti.

Herhangi bir tavsiyesi veya fikri olan var mı?

+0

Yani düz bir Ekip koleksiyonuyla başlıyorsunuz ve bir ağaç oluşturmak mı istiyorsunuz? Bence burada sadece LINQ'dan daha fazlasına ihtiyacınız olacak (yine de yanlış olduğum için çok ilgilenecektim). Ekip koleksiyonunuzda yinelediğinizde, bir ağaç inşa etmeniz gerekecek, bir grup s grubunun değil. –

+0

Üzgünüm, evet, bu takımların düz bir listesi olduğunu söylemeliydim. – ChrisO

cevap

4

İlk olarak, TeamGrouping, aslında olması gerekenden biraz daha karmaşıktır.

public class TeamNode 
{ 
    public Team Value { get; set; } 
    public IEnumerable<TeamNode> Children { get; set; } 
} 

Sonraki biz takımların bizim dizisini almak ve her biri için bir düğüm oluşturmak gerekir: Bütün gereken Team nesne ve çocuklar için başlı başına bir dizisidir. Ardından, ebeveyn kimliğine göre gruplandırmak için ToLookup'u kullanırız. (GroupBy kullanımınız buna çok yakındır, ancak ToLookup daha kolay olacaktır.) Son olarak, her düğümün çocuğunu bu düğüm için arama değeri olarak ayarlayabiliriz (anahtarın yoksa, ILookup boş bir sıra döndüreceğini unutmayın. Var, böylece bizim yaprakları mükemmel ele alınacaktır. Bunu bitirmek için, tüm üst düğümleri null numaralı bir üst kimlikle tüm düğümleri arayarak döndürebiliriz.

public static IEnumerable<TeamNode> CreateTree(IEnumerable<Team> allTeams) 
{ 
    var allNodes = allTeams.Select(team => new TeamNode() { Value = team }) 
     .ToList(); 
    var lookup = allNodes.ToLookup(team => team.Value.ParentTeamId); 
    foreach (var node in allNodes) 
     node.Children = lookup[node.Value.TeamId]; 
    return lookup[null]; 
} 
1

Öncelikle böyle bir nesne gerekeceği için Takım nesne olabilir: Sonra

public class Team 
{ 
    public ParentId {get;set;} 
    public IEnumerable<Team> ChildTeams{get;set;} 
} 

bir özyinelemeli fonksiyon ilk çağrı ebeveyn için bir null geçer

private IEnumerable<Team> BuildTeams(IEnumerable<Team> allTeams, 
                int? parentId) 
    { 
     var teamTree = new List<Team>(); 
     var childTeams = allTeams.Where(o => o.ParentId == parentId).ToList(); 

     foreach (var team in childTeams) 
     { 
      var t = new Team(); 
      var children = BuildTeams(allTeams, team.TeamID); 
      t.ChildTeams = children; 
      teamTree.Add(t); 
     } 

     return teamTree ; 
    } 

ve çekeceğim null ebeveyni olan tüm takımlar :), takımlarınızın ebeveyn için null olmadığını fark etsem de, şu anda en üst seviye olanları nasıl belirlediğinizden emin değil misiniz?

+0

Bu iyi çalışıyor, benim elde edemediğim bir şey, neden yeni Team nesnesi oluşturuyorsunuz, null mülklerini her yerde alacaksınız, neden sadece 'ekip' nesnesini geçmiyorsunuz? – Martin