C# 从人员树生成团队树的正确递归方法是什么?

C# 从人员树生成团队树的正确递归方法是什么?,c#,recursion,C#,Recursion,我有一个Person对象,它具有以下属性 public class Person { public string FirstName; public string LastName; public string TeamName; public Person Manager; public IEnumerable<Person> DirectReports; } 根据这些数据,我现在正试图转换以生成团队的层次结构,因此我有如下内容: foreach (

我有一个Person对象,它具有以下属性

public class Person
{
   public string FirstName;
   public string LastName;
   public string TeamName;
   public Person Manager;
   public IEnumerable<Person> DirectReports;
}
根据这些数据,我现在正试图转换以生成团队的层次结构,因此我有如下内容:

foreach (Person direct in person.DirectReports)
{
       foreach (Person subDirect in direct.DirectReports)
       {
            etc . . .
       }
}
 public class Team
 {
    public string TeamName;
    public IEnumerable<Team> SubTeams;
    public IEnumerable<Person> PeopleInTeam;
}
公共类团队
{
公共字符串组名;
公共可数子群;
公众参与人数;
}
请注意,如果一个人的directReports可能具有或可能不具有相同的团队名称,则个人层次结构中的人员级别数不一定与团队层次结构中的级别数相同

例如:

| Person| ParentPerson | TeamName | | Bill | "" | Management | | Joe | Bill | Management | | Scott | Bill | Marketing | | Jim | Bill | Technology | | Mark | Scott | Marketing | | Bob | Joe | Marketing | |个人|家长|团队名称| |法案| | |管理| |乔|比尔|管理| |斯科特|比尔|营销| |吉姆|比尔|技术| |马克|斯科特|营销| |鲍勃|乔|营销| 所以在转换之后,我会有一个名为“管理”的团队,其中有两个人。它在子团队阵列中有两个项目(一个用于营销,一个用于技术)。每个团队在子团队数组中都没有条目

如何有效地将这种人员层次结构转换为团队层次结构是最好的方法?我在下面列出了代码,但它似乎失败了。现在,我正在遍历每个人和他们的直接下属,创建一个团队词典,一次将每个人添加到一个团队中,但这似乎相当缓慢。下面是一个例子

 Dictionary<string, Team> teams = new Dictionary<string, Team>();

 foreach (Person direct in person.DirectReports)
 {
       if (teams.ContainsKey(direct.TeamName)
       {
              var team = teams[direct.TeamName];
              team.People.Add(direct);
       }
       else
       {
            var team = new Team(){TeamName = direct.TeamName};
            team.People.Add(direct);
            teams[direct.TeamName] = team;
       }
       foreach (Person subDirect in direct.DirectReports)
       {
            etc . . .
       }
}
Dictionary teams=newdictionary();
foreach(个人直接面对面。直接报告)
{
if(teams.ContainsKey(direct.TeamName)
{
var team=teams[direct.TeamName];
team.People.Add(直接);
}
其他的
{
var team=new team(){TeamName=direct.TeamName};
team.People.Add(直接);
团队[direct.TeamName]=团队;
}
foreach(direct.DirectReports中的Person子目录)
{
等
}
}

如果您在树的顶部只有一个人员列表,那么我们可以尝试以下方法:

public void ConstructTeams(IEnumerable<Person> topPeople,
    Dictionary<string, Team> teamsByName)
{
    foreach (Person person in topPeople)
    {
        // Add person to their team. Create one if it doesn't exist
        Team matchingTeam;
        if (teamsByName.TryGetValue(person.TeamName, out matchingTeam))
        {
            matchingTeam.PeopleInTeam.Add(person);
        }
        else
        {
            // Create a new team and update its parent team
            matchingTeam = new Team
            {
                TeamName = direct.TeamName
                PeopleInTeam = new List<Person>()
            };
            matchingTeam.PeopleInTeam.Add(person);
            teamsByName.Add(matchingTeam.TeamName, matchingTeam);

            // The manager's team should already exist because we traversing the
            // Person tree/forest from the roots to the leaves
            if (person.Manager != null)
            {
                teamsByName[person.Manager.TeamName].SubTeams.Add(matchingTeam);
            }
        }

        // Recursively fill in the direct reports
        ConstructTeams(person.DirectReports, teamsByName);
    }
}
公共团队(IEnumerable topPeople,
字典组(名称)
{
foreach(倾倒人群中的人)
{
//将人员添加到他们的团队。如果不存在,则创建一个
团队匹配团队;
if(teamsByName.TryGetValue(person.TeamName,out matchingTeam))
{
匹配team.PeopleInTeam.Add(person);
}
其他的
{
//创建新团队并更新其父团队
matchingTeam=新团队
{
TeamName=direct.TeamName
PeopleInTeam=新列表()
};
匹配team.PeopleInTeam.Add(person);
teamsByName.Add(matchingTeam.TeamName,matchingTeam);
//经理的团队应该已经存在,因为我们正在穿越
//从根到叶的人-树/森林
if(person.Manager!=null)
{
teamsByName[person.Manager.TeamName].SubTeams.Add(matchingTeam);
}
}
//递归填写直接下属
施工团队(person.DirectReports、teamsByName);
}
}
如果你有一个所有人的简单列表,这里有一个解决方案

public IEnumerable<Team> ConstructTeams(IEnumerable<Person> allPeople)
{
    var teams = allPeople.GroupBy(person => person.TeamName)
        .Select(grouping => new Team
        {
            TeamName = grouping.Key,
            // I think this works, but IGroupings are weird and I don't
            // have a compiler with me
            PeopleInTeam = grouping.ToList()
        });

    // Set SubTeams
    // Group the teams by parent team. We assumed that
    // no team has two parent teams
    var teamsGroupedByParentTeam = teams
        .GroupBy(team => team.PeopleInTeam.First().TeamName);

    foreach (var groupOfTeams in teamsGroupedByParentTeam)
    {
        var parentTeam = teams.Single(team => team.TeamName == teamsGroupedByParentTeam.TeamName);
        parentTeam.SubTeams = groupOfTeams.ToList();
    }

    return teams;
}
公共IEnumerable团队(IEnumerable allPeople)
{
var teams=allPeople.GroupBy(person=>person.TeamName)
.选择(分组=>新团队
{
TeamName=分组.Key,
//我认为这是可行的,但我觉得分组很奇怪,我不这么认为
//带个编译器来
PeopleInTeam=grouping.ToList()
});
//设置子团队
//按父团队对团队进行分组。我们假设
//没有一个团队有两个父团队
var teamsGroupedByParentTeam=团队
.GroupBy(team=>team.PeopleInTeam.First().TeamName);
foreach(团队中的var GroupOfTeam按父团队分组)
{
var parentTeam=teams.Single(team=>team.TeamName==teamsGroupedByParentTeam.TeamName);
parentTeam.SubTeams=groupOfTeams.ToList();
}
返回队;
}

这里有一个基本的解决方案,可以用作框架

它并不理想:尤其是,
字典
不是一个好的数据结构,因为我们最终只是循环遍历所有的值。构建一个类似于
字典
的东西,从一个部门映射到其子部门的名称会更有用

但它应该给你一个工作的基础

void Main()
{
    var bill = new Person { FirstName = "Bill", TeamName = "Management" };
    var joe = new Person { FirstName = "Joe", Manager = bill, TeamName = "Management" };
    var scott = new Person { FirstName = "Scott", Manager = bill, TeamName = "Marketing" };
    var jim = new Person { FirstName = "Jim", Manager = bill, TeamName = "Technology" };
    var mark = new Person { FirstName = "Mark", Manager = scott, TeamName = "Marketing" };
    var bob = new Person { FirstName = "Bob", Manager = joe, TeamName = "Marketing" };
    var ted = new Person { FirstName = "Ted", Manager = jim, TeamName = "IT Support" };

    var people = new[] { bill, joe, scott, jim, mark, bob, ted };

    var teamParents = people.Select (p => new { Team = p.TeamName, ParentTeam = p.Manager == null ? null : p.Manager.TeamName });

    // don't let a team be its own parent
    teamParents = teamParents.Where (p => !p.Team.Equals(p.ParentTeam));

    // make sure they're all unique
    teamParents = teamParents.Distinct();

    // put it in a dictionary
    var teamHierarchy = teamParents.ToDictionary (p => p.Team, q => q.ParentTeam);

    foreach (string root in teamHierarchy.Where (h => h.Value == null).Select (h => h.Key))
    {    
        PrintSubteams(teamHierarchy, 0, root);
    }    
}

private void PrintSubteams(Dictionary<string, string> hierarchy, int level, string root)
{
    for (int i = 0; i < level; i++)
    {
        Console.Write("    ");
    }

    Console.WriteLine(root);

    foreach (string child in hierarchy.Where (h => h.Value == root).Select(h => h.Key))
    {
        PrintSubteams(hierarchy, level + 1, child);
    }
}

public class Person
{
    public string FirstName;
    public string LastName;
    public string TeamName;
    public Person Manager;
    public IEnumerable<Person> DirectReports;
}
void Main()
{
var-bill=新人{FirstName=“bill”,TeamName=“Management”};
var-joe=新人{FirstName=“joe”,Manager=bill,TeamName=“Management”};
var scott=新人{FirstName=“scott”,Manager=bill,TeamName=“Marketing”};
var jim=新人{FirstName=“jim”,Manager=bill,TeamName=“Technology”};
var mark=新人{FirstName=“mark”,Manager=scott,TeamName=“Marketing”};
var bob=新人{FirstName=“bob”,Manager=joe,TeamName=“Marketing”};
var ted=新人{FirstName=“ted”,Manager=jim,TeamName=“IT支持”};
var people=new[]{比尔、乔、斯科特、吉姆、马克、鲍勃、特德};
var teamParents=people.Select(p=>new{Team=p.TeamName,ParentTeam=p.Manager==null?null:p.Manager.TeamName});
//不要让团队成为自己的父母
teamParents=teamParents.Where(p=>!p.Team.Equals(p.ParentTeam));
//确保它们都是独一无二的
teamParents=teamParents.Distinct();
//把它放在字典里
var teamHierarchy=teamParents.ToDictionary(p=>p.Team,q=>q.ParentTeam);
foreach(teamHierarchy.Where(h=>h.Value==null)中的字符串根。选择(h=>h.Key))
{    
打印子团队(团队层次结构,0,根);
}    
}
私有void printSubteam(字典层次结构、int级别、字符串根)
{
对于(int i=0;
Management
    Marketing
    Technology
        IT Support