前言
本節是實現統計排名的一點技巧,可能有一部分童鞋在實現排名統計繞了一大圈,最后還不如兩行代碼就搞定,代碼清晰而可讀性強,接下來我們來一起來看看。
統計排名
我們知道在SQL Server中可以利用Row_Number、Rank等函數進行排名,在MySQL中可以利用變量方式來實現排名,對於計算操作我傾向於放在內存中來操作,而數據庫只是做簡單的操作,盡管各個數據庫可能提供了對應函數來進行處理,但是一旦數據量大時,可能擱置到內存中計算不失為一種好的方式。接下來我們來看看在C#中如何利用LINQ來進行排名,比如我們需要統計截止到當前時間,患者咨詢的醫生的人次排名(同一患者在同一天咨詢同一醫生多次只算一次),假設我們從數據庫查詢出醫生姓名和患者咨詢醫生的次數,如下:
public class Consult { public string Name { get; set; } public int Times { get; set; } public int Rank { get; set; } }
var consults = new List<Consult>() { new Consult() { Name = "張三", Times = 1 }, new Consult() { Name = "李四", Times = 1 }, new Consult() { Name = "王五", Times = 2 }, new Consult() { Name = "趙六", Times = 3 }, new Consult() { Name = "小明", Times = 0 }, new Consult() { Name = "小紅", Times = 0 } };
我們得到了所有醫生被咨詢的次數和姓名,接下來我們通過LINQ繼續對其進行操作,這里最重要需要了解的是投影(Select或SelectMany)具有索引的參數,知道有索引這個參數一切就好辦了,因為次數越大說明排名越靠前,所以首先我們需要對上述集合進行倒序,然后再對倒序后的結果通過次數進行分組,分組后將導致不同次數在不同集合中(反之,同次數在相同集合中),然后通過SelectMany獲取到分組后的指定集合和索引,最后對此集合進行投影就得到了最終的結果排名,代碼如下:
var result = consults.OrderByDescending(d => d.Times) .GroupBy(d => d.Times) .SelectMany((g, i) => g.Select(e => new Consult() { Name = e.Name, Times = e.Times, Rank = i + 1 })).ToList();

總結
上述需注意索引從0開始,所以需要加1,同時針對相同次數排名會相同,通過此種實現排名的方式,邏輯清晰且代碼精簡,當然,投影中含有索引參數也還可應用於其他用途,只不過用於排名的場景還是比較多,暫且到這里,感謝您的閱讀。
