Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何根据ID从员工薪资第二高的员工集合中选择具有LINQ的不同员工?_C#_.net_Linq - Fatal编程技术网

C# 如何根据ID从员工薪资第二高的员工集合中选择具有LINQ的不同员工?

C# 如何根据ID从员工薪资第二高的员工集合中选择具有LINQ的不同员工?,c#,.net,linq,C#,.net,Linq,看看下面的例子。这里的雇员ID=2,也就是史蒂夫有3个副本。 我只想要每个ID的一个记录。我想要选择薪水第二高的记录。因此,在史蒂夫的情况下,选择将是两个有160个作为工资的史蒂文之一 public class Employee { public int ID { get; set; } public string Name { get; set; } public int Salary { g

看看下面的例子。这里的雇员ID=2,也就是史蒂夫有3个副本。 我只想要每个ID的一个记录。我想要选择薪水第二高的记录。因此,在史蒂夫的情况下,选择将是两个有160个作为工资的史蒂文之一

       public class Employee
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public int Salary { get; set; }

            public static List<Employee> GetAllEmployees()
            {
                return new List<Employee>()
        {
            new Employee { ID = 1, Name = "Mark", Salary = 100 },
            new Employee { ID = 2, Name = "Steve", Salary = 150 },
            new Employee { ID = 2, Name = "Steve", Salary = 160 },
            new Employee { ID = 2, Name = "Steve", Salary = 160 },
            new Employee { ID = 2, Name = "Steve", Salary = 165 },
            new Employee { ID = 3, Name = "Ben", Salary = 140 }                

        };
            }
        }
我知道如何根据属性获取不同的记录:

var result = Employee.GetAllEmployees().GroupBy(x=>x.ID).Distinct();
但另一方面我迷路了

请注意,我只寻找LINQ lambda/扩展语法答案。谢谢

一种方法是在GroupBy之后使用Select。这会将每个组转换为一名员工

Employee.GetAllEmployees().GroupBy(x=>x.ID).Select(x => FindSecondHighest(x));
其中FindSecondHighest应该如下所示:

private static Employee FindSecondHighest(IEnumerable<Employee> employees) {
    var list = employees.ToList();
    if (list.Count == 1) { return list[0]; }
    return list.OrderByDescending(x => x.Salary).Skip(1).First();
}
首先,失去明确的目标。根据定义,分组是唯一的

根据您的要求,您需要按薪资降序排列分组结果,然后选择第二个。仅当分组包含多个项时才执行此操作。因此,这应该是可行的:

    var result = Employee.GetAllEmployees()
        .GroupBy(x => x.ID)
        .Select(x => (x.Count() > 1 ? x.GroupBy(y => y.Salary).Skip(1).Select(y => y.First()) : x).First()
        );
Employee.GetAllEmployees().Where(x => {
    recordsWithID = Employee.GetAllEmployees().Where(y => y.ID == x.ID).OrderByDescending(y => y.Salary);

    recordToReturn = recordsWithID.Count > 1 ? recordsWithID.Skip(1).First() : recordsWithID.First();

    return x.ID == recordToReturn.ID;
});

编辑:根据评论更新了我的答案,我们需要按薪资分组,然后跳过1,以缓解第二条记录也具有最高薪资值的情况。

以下操作应该有效:

    var result = Employee.GetAllEmployees()
        .GroupBy(x => x.ID)
        .Select(x => (x.Count() > 1 ? x.GroupBy(y => y.Salary).Skip(1).Select(y => y.First()) : x).First()
        );
Employee.GetAllEmployees().Where(x => {
    recordsWithID = Employee.GetAllEmployees().Where(y => y.ID == x.ID).OrderByDescending(y => y.Salary);

    recordToReturn = recordsWithID.Count > 1 ? recordsWithID.Skip(1).First() : recordsWithID.First();

    return x.ID == recordToReturn.ID;
});
首先,在主谓词中,我们选择具有x ID的所有用户。然后,如果有多个具有该ID的记录,我们将获得工资第二高的记录,否则,我们只选择具有该ID的唯一记录。然后,如果对于x的ID组,x是实际需要的记录,因此x是唯一一个ID为的记录,或者x是ID为x的记录中工资第二高的记录,返回x,否则返回x


我目前无法测试这一点,因为我没有在电脑前,但这会给你一个想法。

你可以使用.GroupBy和.Select尝试类似的方法:


如果组计数为1,则不需要排序。返回X您如何保证第二个记录也有第二个最高工资?因为它可能与第一条记录具有相同的值。捕捉得好。一种方法是按工资分组,然后跳过1。请看我的最新答案。谢谢。你的答案肯定更具可读性,但我已经标记了杰罗恩的答案,因为他是第一个回答正确的人。
static void Main(string[] args)
{
    List<Employee> secondHighestSalaryPersons = Employee.GetAllEmployees()
         .GroupBy(x => x.Name)
         .Select(x =>
         {
             var group = x.ToList();

             if (group.Count > 1)
                 return group.OrderByDescending(y => y.Salary).Skip(1).FirstOrDefault();
             else
                 return group.FirstOrDefault();
         })
         .ToList();
}