[英]How to select distinct employees with LINQ based on ID from an employee collection where employee 's salary is 2nd highest?
請看下面的例子。 這里員工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 }
};
}
}
期望的輸出:
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 /擴展語法的答案。 謝謝!
一種方法是在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();
}
如果你願意,你可以將方法重寫為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();
}
首先,失去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以緩解第二條記錄也具有最高薪水值的情況。
以下應該有效:
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,否則不返回。
我目前無法測試這個,因為我不在電腦前,但這應該給你一個想法。
您可以使用.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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.