LINQ 递归查询以返回分层的组集 [英] LINQ recursive query to return hierarchical set of groups

查看:26
本文介绍了LINQ 递归查询以返回分层的组集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下模型的列表

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

我正在尝试编写一个递归的 linq 查询,这将使我能够检索如下所示的层次结构

I am trying to write a recursive linq query which will enable me to retrieve a heirarchy that looks like this

Team
    ChildTeams
Team
    Team
        ChildTeams

我尝试了很多方法,也看到了很多类似的问题,但没有一个专门帮助我解决问题.我尝试的最新尝试是这样的:

I've tried many approaches and seen many similar questions but none of them specifically helped me solve the problem. The latest attempt I tried went along these lines:

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 然后将随后返回的组传递到 ToGrouping(IEnumerable) 但这是产生错误的结果.

I would pass the list of teams into the first ToGrouping(IEnumerable<Team>) and then subsequent returned groups into ToGrouping(IEnumerable<TeamGrouping>) but this is producing incorrect results.

有人有什么建议或想法吗?

Anyone have any advice or ideas?

推荐答案

所以首先,您的 TeamGrouping 实际上比它需要的要复杂一些.它所需要的只是 Team 对象和一个自己的孩子序列:

So first, your TeamGrouping is actually a bit more complex than it needs to be. All it needs is the Team object and a sequence of itself for children:

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

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

Next we'll take our sequence of teams and create a node for each one. Then we'll use ToLookup to group them by their parent ID. (Your use of GroupBy is pretty darn close to this, but ToLookup will be easier.) Finally we can just set each node's children to be the lookup value for that node (note that ILookup will return an empty sequence if the key doesn't exist, so our leaves will be handled perfectly). To finish it off we can return all of the top level nodes by just looking up all nodes with a parent ID of 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];
}

这篇关于LINQ 递归查询以返回分层的组集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆