【问题标题】:Organization Chart - Group by Manager to show all employees under him组织结构图 - 按经理分组以显示其下的所有员工
【发布时间】:2020-03-26 16:55:18
【问题描述】:

我编写了下面的代码来显示员工-经理报告,我有分组方式,以便显示一位经理下的所有员工,但它只显示 1 名员工。我错过了什么?

LINQ 按逻辑分组-

var emp = (from m in employee
                       group m by m.ManagerId into g
                       join e1 in employee on g.FirstOrDefault().ManagerId equals e1.EmpId into temp
                       from t1 in temp.DefaultIfEmpty()                       
                       select new 
                       {
                           EmpId = g.FirstOrDefault().EmpId,
                           EmployeeName = g.FirstOrDefault().EmployeeName,
                           Gender = g.FirstOrDefault().Gender,
                           ManagerId = t1?.ManagerId ?? 0  ,
                           ManagerName = t1?.EmployeeName ?? "Top of the Chain",
                           Designation = g.FirstOrDefault().Designation
                       }).ToList();

我添加了 AddEmployee() 和 RemoveEmployee() 的实现如下,调用如下,但 Removeemployee 不会从层次结构中删除员工??

employee.Add(new Employee { EmpId = 11, EmployeeName = "Chris Harris", Gender = 'M', ManagerId = 7, Designation = "Executive" });
            employee.Add(new Employee { EmpId = 13, EmployeeName = "Rocky Balbo", Gender = 'M', ManagerId = null, Designation = "CEO" });

            int? ceo = null;

            AddEmployee(new Employee { EmpId = 2, EmployeeName = "Rohan Kumar", Gender = 'M', ManagerId = 13, Designation = "Application Architect"  });
            AddEmployee(new Employee { EmpId = 1, EmployeeName = "Mohan Kumar", Gender = 'M', ManagerId = 2, Designation = "Tech Lead" });
            RemoveEmployee(new Employee { EmpId = 9, EmployeeName = "Rogger Binny", Gender = 'M', ManagerId = 7, Designation = "Sales Executive" });
            GetHierarchy(ceo, 0, "");

   static void AddEmployee(Employee empDetails)
        {
            employee.Add(empDetails);
        }

        static void RemoveEmployee(Employee empDetails)
        {
            employee.Remove(empDetails);
        } 

public class Employee
    {
        public int EmpId { get; set; }
        public string EmployeeName { get; set; }
        public char Gender { get; set; }
        public int? ManagerId { get; set; }
        public string Designation { get; set; }
        public string ManagerName { get; set; }
    }

List<Employee> employee = new List<Employee>();
            employee.Add(new Employee { EmpId = 3, EmployeeName = "Andrea Ely", Gender = 'F', ManagerId = 6, Designation = "Tech Head"});
            employee.Add(new Employee { EmpId = 4, EmployeeName = "John Eward", Gender = 'M', ManagerId = 3, Designation = "General" });
            employee.Add(new Employee { EmpId = 5, EmployeeName = "Lesli Mac", Gender = 'F', ManagerId = 3, Designation = "Staff" });
            employee.Add(new Employee { EmpId = 6, EmployeeName = "Satinder Singh", Gender = 'M', ManagerId = 13, Designation = "President" });
            employee.Add(new Employee { EmpId = 7, EmployeeName = "Amit Sarna", Gender = 'M', ManagerId = 13, Designation = "Vice President" });
            employee.Add(new Employee { EmpId = 8, EmployeeName = "David Steward", Gender = 'M', ManagerId = 7, Designation = "General" });
            employee.Add(new Employee { EmpId = 9, EmployeeName = "Rogger Binny", Gender = 'M', ManagerId = 7, Designation = "Sales Executive" });
            employee.Add(new Employee { EmpId = 10, EmployeeName = "Emy jackson", Gender = 'F', ManagerId = 7, Designation = "Sales Executive" });
            employee.Add(new Employee { EmpId = 11, EmployeeName = "Chris Harris", Gender = 'M', ManagerId = 7, Designation = "Executive" });
            employee.Add(new Employee { EmpId = 13, EmployeeName = "Rocky Balbo", Gender = 'M', ManagerId = null, Designation = "CEO" });

var emp = (from m in employee
                       group m by m.ManagerId into g
                       join e1 in employee on g.FirstOrDefault().ManagerId equals e1.EmpId into temp
                       from t1 in temp.DefaultIfEmpty()                       
                       select new 
                       {
                           EmpId = g.FirstOrDefault().EmpId,
                           EmployeeName = g.FirstOrDefault().EmployeeName,
                           Gender = g.FirstOrDefault().Gender,
                           ManagerId = t1?.ManagerId ?? 0  ,
                           ManagerName = t1?.EmployeeName ?? "Top of the Chain",
                           Designation = g.FirstOrDefault().Designation
                       }).ToList();

            Console.WriteLine("--------------Printing Manager-Employee Hierarchy-------------");
            foreach (var empDetails in emp)
            {               
                Console.WriteLine("Emp Name is {0} ManagerName is {1}", empDetails.EmployeeName, empDetails.ManagerName);                
            }

【问题讨论】:

    标签: c# linq group-by


    【解决方案1】:

    使用递归算法:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication3
    {
        class Program
        {
            static List<Employee> employees;
            static void Main(string[] args)
            {
                employees = new List<Employee>();
                employees.Add(new Employee { EmpId = 3, EmployeeName = "Andrea Ely", Gender = 'F', ManagerId = 6, Designation = "Tech Head"});
                employees.Add(new Employee { EmpId = 4, EmployeeName = "John Eward", Gender = 'M', ManagerId = 3, Designation = "General" });
                employees.Add(new Employee { EmpId = 5, EmployeeName = "Lesli Mac", Gender = 'F', ManagerId = 3, Designation = "Staff" });
                employees.Add(new Employee { EmpId = 6, EmployeeName = "Satinder Singh", Gender = 'M', ManagerId = 13, Designation = "President" });
                employees.Add(new Employee { EmpId = 7, EmployeeName = "Amit Sarna", Gender = 'M', ManagerId = 13, Designation = "Vice President" });
                employees.Add(new Employee { EmpId = 8, EmployeeName = "David Steward", Gender = 'M', ManagerId = 7, Designation = "General" });
                employees.Add(new Employee { EmpId = 9, EmployeeName = "Rogger Binny", Gender = 'M', ManagerId = 7, Designation = "Sales Executive" });
                employees.Add(new Employee { EmpId = 10, EmployeeName = "Emy jackson", Gender = 'F', ManagerId = 7, Designation = "Sales Executive" });
                employees.Add(new Employee { EmpId = 11, EmployeeName = "Chris Harris", Gender = 'M', ManagerId = 7, Designation = "Executive" });
                employees.Add(new Employee { EmpId = 13, EmployeeName = "Rocky Balbo", Gender = 'M', ManagerId = null, Designation = "CEO" });
    
                int? ceo = null;
                GetHierarchy(ceo, 0, "");
    
            }
            static void GetHierarchy(int? managerID, int level, string managerName)
            {
                List<Employee> group = employees.Where(x => x.ManagerId  == managerID).ToList();
                foreach (Employee empDetails in group)
                {
                    Console.WriteLine("{0}Emp Name is {1} ManagerName is {2}", new string(' ', 5 * level), empDetails.EmployeeName, managerName);
                    GetHierarchy(empDetails.EmpId, level + 1, empDetails.EmployeeName);
                }
            }
        }
        public class Employee
        {
            public int EmpId { get; set; }
            public string EmployeeName { get; set; }
            public char Gender { get; set; }
            public int? ManagerId { get; set; }
            public string Designation { get; set; }
            public string ManagerName { get; set; }
        }
    
    
    }
    

    【讨论】:

    • 只是每个级别要标识的空格数。相当于每一层都有一个标签。
    • 你能看看我修改后的帖子,我添加了 AddEmployee() 和 RemoveEmployee(),RemoveEmployee() 不起作用?你能看看吗?
    • RemoveAll 不会删除已删除员工的孩子。因此,被撤职员工的任何孩子不久就会拥有经理。如果您移除经理,您必须带走直系子女并给他们一个新经理。
    • 如果我使用 RemoveAll 整个链会被删除,而应该只删除那个经理/雇员,并且它的所有孩子都应该开始向他的上线经理报告。我们如何在上面的代码中实现这一点?
    • RemoveAll 对您没有任何作用。只需使用删除。在移除之前,您必须找到所有孩子并将他们的经理更改为您要移除的员工的经理。
    【解决方案2】:

    根据评论更新

    当调用RemoveEmployee 时,您将创建一个新的object,这意味着内存中的一个新引用。那么这两个objects 不相等(employee 列表中的对象和新的object),但是值(empId...的值)是相同的。

    要从employee 中删除元素,您有两种解决方案:
    1 - 使用RemoveAll,并通过empId 过滤或创建其他采用empId 的方法,如以下代码:

    void RemoveEmployee(Employee empDetails)
    {
        employee.RemoveAll(emp => emp.EmpId == empDetails.EmpId);
    }
    void RemoveEmployee(int empId)
    {
        employee.RemoveAll(emp => emp.EmpId == empId);
    }
    

    2 - 调用RemoveEmployee 时进行过滤,如以下代码:

    RemoveEmployee(employee.First(emp => emp.EmpId == 9));
    

    旧解决方案

    如果理解正确,这里的问题是ManagerName,你的代码很好,但是你需要避免FirstOrdDefault,通过循环g中的每个元素来获得预期的结果,就像下面的代码:

    var groupedEmp = (from m in employee
                group m by m.ManagerId into g
                join e1 in employee on g.Key equals e1.EmpId into temp
                from t1 in temp.DefaultIfEmpty()
                select new
                {
                    g = g,
                    t1 = t1
                });
    
    var empList = groupedEmp
               .SelectMany(x => x.g.Select(y =>
                    new Employee
                    {
                        EmpId = y.EmpId,
                        EmployeeName = y.EmployeeName,
                        Designation = y.Designation,
                        Gender = y.Gender,
                        ManagerId = y.ManagerId ?? 0,
                        ManagerName = x.t1?.EmployeeName ?? "Top"
                    })).ToList();
    
    

    测试

    foreach(Employee employe in empList)
    {
        Console.WriteLine($"EmpId  :  {employe.EmpId}, EmpName  :  {employe.EmployeeName}, MngId  :  {employe.ManagerId}, MngName  :  {employe.ManagerName}");
    }
    

    结果

    EmpId  :  3, EmpName  :  Andrea Ely, MngId  :  6, MngName  :  Satinder Singh
    EmpId  :  4, EmpName  :  John Eward, MngId  :  3, MngName  :  Andrea Ely
    EmpId  :  5, EmpName  :  Lesli Mac, MngId  :  3, MngName  :  Andrea Ely
    EmpId  :  6, EmpName  :  Satinder Singh, MngId  :  13, MngName  :  Rocky Balbo
    EmpId  :  7, EmpName  :  Amit Sarna, MngId  :  13, MngName  :  Rocky Balbo
    EmpId  :  8, EmpName  :  David Steward, MngId  :  7, MngName  :  Amit Sarna
    EmpId  :  9, EmpName  :  Rogger Binny, MngId  :  7, MngName  :  Amit Sarna
    EmpId  :  10, EmpName  :  Emy jackson, MngId  :  7, MngName  :  Amit Sarna
    EmpId  :  11, EmpName  :  Chris Harris, MngId  :  7, MngName  :  Amit Sarna
    EmpId  :  13, EmpName  :  Rocky Balbo, MngId  :  0, MngName  :  Top
    

    希望对你有所帮助。

    【讨论】:

    • @user662285 你能试试我的解决方案吗?
    • 谢谢,您的解决方案有效,现在我遇到了 RemoveEmployee() 的问题,请参阅上面的实现
    • @user662285,你不能通过创建新对象来删除元素,请检查我的提议
    • @jsajid:如果我使用 RemoveAll 整个链会被删除,而应该只删除那个经理/雇员,并且它的所有孩子都应该开始向他的上线经理报告。我们如何在上面的代码中实现这一点?
    • @user662285 注意,RemoveAll 带一个条件,然后 not 会删除整个员工,你也可以使用你自己的函数,这样调用它:RemoveEmployee(employee.First(emp =&gt; emp.EmpId == 9)); 但你不能创建当您想删除新员工时。
    猜你喜欢
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-28
    • 2021-11-05
    • 2016-06-15
    • 1970-01-01
    相关资源
    最近更新 更多