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 ChildTeams { get; set; } public IEnumerable Grouping { get; set; } } private IEnumerable ToGrouping(IEnumerable teams) { return teams.GroupBy(t => t.ParentTeamId, (parentTeam, childTeams) => new TeamGrouping {ParentTeamId = parentTeam, ChildTeams = childTeams}); } private IEnumerable ToGrouping(IEnumerable teams) { return teams.GroupBy(t => t.ParentTeamId, (parentTeam, childTeams) => new TeamGrouping{ParentTeamId = parentTeam, Grouping = childTeams}); } 

我会将团队列表传递给第一个ToGrouping(IEnumerable) ,然后将后续返回的组ToGrouping(IEnumerable)ToGrouping(IEnumerable)但这会产生不正确的结果。

任何人有任何建议或想法?

首先,你的TeamGrouping实际上比它需要的要复杂一些。 它需要的只是Team对象及其自身的序列:

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

接下来,我们将采用我们的团队序列并为每个团队创建一个节点。 然后我们将使用ToLookup按父ID分组。 (你对GroupBy使用非常接近于此,但ToLookup会更容易。)最后,我们可以将每个节点的子节点设置为该节点的查找值(请注意,如果键不是,则ILookup将返回空序列存在,所以我们的叶子将被完美处理)。 为了完成它,我们可以通过查找父ID为null所有节点来返回所有顶级节点。

 public static IEnumerable CreateTree(IEnumerable 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]; } 

首先你需要一个像这样的对象,所以Team对象可能是:

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

然后是递归函数

 private IEnumerable BuildTeams(IEnumerable allTeams, int? parentId) { var teamTree = new List(); 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 ,并且将拉出所有具有null父级的团队:),虽然我注意到你的团队没有父级的null,所以不确定你如何识别当前的顶级队员?