【问题标题】:Find max count of a list of custom types查找自定义类型列表的最大计数
【发布时间】:2013-06-18 22:34:40
【问题描述】:

我有一个模拟应用程序,其中继承链像 Employee,Manager,President

Employee 类看起来像

class Employee
    {
        public int EmployeeId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime HireDate { get; set; }

        public Employee() 
        { 
        }
    }

Manager 类看起来像

 class Manager : Employee
    {

        private List<Employee> employeesManaged = new List<Employee>();
        public List<Employee> EmployeesManaged
        {
            get { return employeesManaged; }
            set { employeesManaged = value; }
        }
    }

我想写一个方法来找到管理最多员工(其EmployeesManaged.Count 属性最大)的经理。我目前有两个问题。

  1. 正如您将在下面的代码中看到的,我必须手动将每个 Manager 添加到 List 变量中。这不是一个长期的解决方案。什么是解决这个问题的有效、简洁的方法?

  2. 我的 Linq 语法不正确。

我认为第一个问题是最紧迫的。如果有 1000 个 Employee 对象,我将如何避免将每个对象添加到列表中?

 public static Manager  GetBestManager(List<Manager> managerList)
        {
            Manager m = managerList.Select(x => x.EmployeesManaged).Max();

        }

我的主要方法

Employee e = new Employee();
            e.EmployeeId = 101;
            e.FirstName = "Tom";
            e.LastName = "Jones";
            e.HireDate = DateTime.Now.Subtract(TimeSpan.FromDays(40));

            Employee e2 = new Employee();
            e2.EmployeeId = 102;


            Employee e3 = new Employee();
            e3.EmployeeId = 103;


            Manager m = new Manager();
            m.EmployeeId = 201;
            m.EmployeesManaged.Add(e);
            m.EmployeesManaged.Add(e2);

            Manager m2 = new Manager();
            m2.EmployeesManaged.Add(e3);

            List<Manager> mList = new List<Manager>();
            mList.Add(m);
            mList.Add(m2);
            Manager.GetBestManager(mList);

使用当前语法,我收到错误“无法将类型 Employee 隐式转换为 Manager”

【问题讨论】:

标签: c# asp.net linq


【解决方案1】:

1) 这取决于数据的来源。一个数据库,来自磁盘的文件,在内存集合中。通常是List 或由源确定的任何结构。

2) 您的 LINQ 获得了最大数量,而不是数量最多的 Manager。试试:

public static Manager GetBestManager(List<Manager> managerList)
{
    Manager m = managerList.OrderByDescending(x => x.EmployeesManaged.Count).First();
    return m;
}

【讨论】:

  • 这不起作用,因为Employee 没有实现IComparable...(EmployeesManagedList&lt;Employee&gt;,而不是int)..
【解决方案2】:

有效的快速且可能更脏的解决方案:

return managerList
       .OrderByDescending(x => x.EmployeesManaged.Count)
       .FirstOrDefault();

【讨论】:

    【解决方案3】:

    查看我在这篇文章中的回答: How can I get LINQ to return the object which has the max value for a given property?

    您可以在 System.Linq 中使用 Aggregate 函数

    Aggregate 更快,因为它只在集合中运行一次,然后取最大的。 OrderBy 本质上必须做一个成本更高的冒泡排序。

    【讨论】:

    • 感谢您的链接,将查看。
    【解决方案4】:

    我想这可能是你想要的:

    public static Manager GetBestManager(this IList<Manager> managerList) {
        Func<Manager, int> getCount=x => x.EmployeesManaged.Count;
        return managerList.First(x => getCount(x)==managerList.Max(getCount));
    }
    

    如果有多个经理拥有相同数量的员工,则返回第一个。之所以没有使用FirstOrDefault,是因为最大值是从列表中获取的,我们总是可以找到一个匹配最大值的管理器,除非集合是空的。

    那么,为什么要使用FirstOrDefault返回null而不是抛出异常让调用者知道谁传递了一个空列表呢?

    【讨论】:

    • 为什么要为不异常的东西抛出异常?这里不需要例外。优雅地处理它。
    • @SimonWhitehead:那么也许TryGetBestManager 带有out 参数会更好。
    猜你喜欢
    • 1970-01-01
    • 2021-05-17
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 2019-07-15
    • 1970-01-01
    • 2020-07-18
    相关资源
    最近更新 更多