2013-11-15 2 views
6

의 계층 적 집합을 반환하는LINQ 재귀 쿼리는 다음과 같은 모델의 목록을 감안할 때 그룹

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

나는이

처럼 보이는 계층 구조를 검색하는 저를 가능하게 할 것이다 재귀 LINQ 쿼리를 작성하는 것을 시도하고있다
Team 
    ChildTeams 
Team 
    Team 
     ChildTeams 

나는 많은 접근법을 시도해 보았지만 많은 비슷한 질문을 보았지만 아무도 특별히이 문제를 해결하지 못했습니다.

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}); 
} 

내가 ToGrouping(IEnumerable<TeamGrouping>)에 처음 ToGrouping(IEnumerable<Team>) 다음 다음 반환 된 그룹으로 팀의 목록을 통과 할 것이다 그러나 이것은 잘못된 결과를 생산하고있다 : I 시도 최신 시도는이 라인을 따라 갔다.

누구나 어떤 조언이나 아이디어가 있습니까?

+0

그래서 평면 팀으로 시작하여 나무를 만들고 싶습니까? 나는 당신이 LINQ 이상을 필요로 할 것이라고 생각한다 (비록 내가 틀린 것으로 증명 될지는 몰라도). 팀 컬렉션을 반복 할 때 IGrouping 컬렉션이 아닌 트리를 만들어야합니다. –

+0

죄송합니다. 그렇다고해서 팀의 목록이 단순하다고 언급 했어야합니다. – ChrisO

답변

4

그래서 먼저 TeamGrouping은 실제로 필요한 것보다 약간 더 복잡합니다.

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

다음 우리 팀 우리의 순서를 가지고 각각의 노드를 만듭니다 :가 필요한 모두는 Team 객체와 어린이를위한 자체의 순서입니다. 그런 다음 ToLookup을 사용하여 상위 ID별로 그룹화합니다. (GroupBy의 사용은 이것에 매우 가깝지만 ToLookup은 더 쉬울 것입니다.) 마침내 각 노드의 자식을 해당 노드의 조회 값으로 설정할 수 있습니다. ILookup은 키가 그렇지 않은 경우 빈 시퀀스를 반환합니다. 그래서 우리의 잎은 완벽하게 취급 될 것입니다). 이 작업을 끝내려면 부모 ID가 null 인 모든 노드를 검색하여 모든 최상위 노드를 반환 할 수 있습니다.

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

첫째로이 같은 개체가 필요합니다, 그래서 팀 객체는 다음과 같을 수 있습니다 : 다음

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

재귀 함수 첫 번째 호출은 부모에 대한 null 통과

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 ; 
    } 

을하고 끌어 귀하의 팀이 부모를위한 null을 가지고 있지 않다는 것을 알았지 만 현재 상위 레벨의 사람들을 어떻게 식별 할 지 확신 할 수 없지만 부모가없는 모든 팀은 :).

+0

잘 작동한다. 내가 얻지 못하는 한 가지 이유는 왜 새 Team 객체를 만들지, 어디에서나 null 속성을 얻을 것이고, 왜 'team' 객체를 전달하지 않을까? – Martin

관련 문제