看下面的例子。在这里,员工ID = 2,也就是史蒂夫有3个重复项。 我只希望每个ID有一个记录。我想选择薪水第二高的记录。因此,在史蒂夫(Steve)的情况下,选择是两个史蒂夫(Steve)帽子之一,工资为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 }
};
}
}
所需的输出:
1 Mark 100
1 Steve 160 //2nd highest salary of steve( there are two such steves so pick any)
1 Mark 100
1 Ben 140
我知道如何基于属性获取不同的记录:
var result = Employee.GetAllEmployees().GroupBy(x=>x.ID).Distinct();
但我却迷失了另一面。
请注意,我仅在寻找LINQ lambda / extension语法答案。谢谢!
答案 0 :(得分:2)
一种方法是在Select
之后使用GroupBy
。这样会将每个小组转变成一名雇员。
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();
}
如果愿意,您可以将方法重写为lambda,但是我觉得这种方法更具可读性。
编辑:
我意识到,如果有两个最高薪水,这实际上并不会获得第二高薪水。要获得第二高的薪水,您可以使用第二个GroupBy
:
private static Employee FindSecondHighest(IEnumerable<Employee> employees) {
var list = employees.ToList();
if (list.Count == 1) { return list[0]; }
return list.GroupBy(x => x.Salary).OrderByDescending(x => x.Key).Skip(1).First();
}
答案 1 :(得分:2)
首先,丢失Distinct()
。根据定义,这些分组是唯一的。
根据您的要求,您需要按薪水(降序)对分组结果进行排序,然后取第二个结果。仅当分组具有多个项目时才执行此操作。结果,这应该起作用:
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()
);
编辑:根据评论更新了我的答案,我们需要按薪水分组,然后跳过1以缓解第二条记录也具有最高薪水值的情况。
答案 2 :(得分:0)
以下方法应该起作用:
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具有x的ID记录中的第二高薪水),则返回x,否则返回。
由于我不在PC前面,因此我目前无法测试,但这应该可以给您一个提示。
答案 3 :(得分:0)
您可以使用.GroupBy
和.Select
尝试这样的事情:
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();
}