Dotnet C# List Sort 各種用法 Dotnet C# List Sort 各種排序用法

Published on Monday, March 6, 2023

.Net Sort

今天來複習一下 .Net 中排序的各種用法,首先是最簡單的由小到大排序

使用 Sort 方法可以直接將資料做正向排序,Sort 方法沒有回傳值會直接對原始資料進行排序

var myList = new List<int>() { 1, 7, 4, 2, 6, 3 };
myList.Sort();

使用 OrderBy 擴充方法需要搭配 Lambda 表達式,並且回傳的是 IEnumerable 需要再做一次轉型,並且賦值回原變數

var myList = new List<int>() { 1, 7, 4, 2, 6, 3 };
myList = myList.OrderBy(x => x).ToList();

反向排序也很簡單,可以先呼叫 Sort 方法,之後在呼叫一次 Reverse 方法

var myList = new List<int>() { 1, 7, 4, 2, 6, 3 };
myList.Sort();
myList.Reverse();

OrderBy 也有專門用來反向排序的擴充方法 OrderByDescending

var myList = new List<int>() { 1, 7, 4, 2, 6, 3 };
myList = myList.OrderByDescending(x => x).ToList();

接下來討論一下字串方面的排序 這邊準備了一個 List String 一樣使用 Sort 方法進行排序
但是要注意 String 的 排序預設會根據電腦的 CultureInfo 不同而有所變化,並不是預設使用 ASCII 進行排序
所以 csharp 有提供了一組 Class StringComparer 讓我們選擇該怎麼樣排序 這邊 StringComparer.Ordinal 就代表按照 ASCII 進行排序

var words = new List<string>(){ "i", "love", "csharp", "i", "love", "sorting" };
words.Sort(StringComparer.Ordinal);
Console.WriteLine(words);

List<String> (6 items)•••
csharp
i
i
love
love
sorting

我們這邊再把第一個 love 改成大寫形式,在進行排序會發現大寫的 Love 變到第一位了,這是因為大寫的 L 為 76 小寫的 c 為 99 所以這時就會把 Love 拉到第一位

var words = new List<string>(){ "i", "Love", "csharp", "i", "love", "sorting"};
words.Sort(StringComparer.Ordinal);
Console.WriteLine(words);

List<String> (6 items)•••
Love
csharp
i
i
love
sorting

當然也可使用 StringComparer.OrdinalIgnoreCase 也是以 ASCII 為基礎但是會忽略掉大小寫

var words = new List<string>(){ "i", "Love", "csharp", "i", "love", "sorting"};
words.Sort(StringComparer.OrdinalIgnoreCase);
Console.WriteLine(words);

List<String> (6 items)•••
csharp
i
i
Love
love
sorting

最後是多條件排序,這個在 SQL 常用到,例如先按照姓來排序在對名作排序就是很常出現的例子 這邊我使用上面字串的資料創建一個字典資料

var words = new List<string>() { "love", "i", "csharp", "love", "i", "sorting", "sorting", "sorting" };
var dict = new Dictionary<string, int>();

foreach (var word in words)
{
	if (!dict.ContainsKey(word)) dict.Add(word, 1);
	else dict[word]++;	
}
	
Console.WriteLine(dict);

Dictionary<String,Int32> (4 items)•••
Key	Value
love	2
i	2
csharp	1
sorting	3

現在我們需要將頻率最高的兩個詞挑選出來,如果頻率一樣就按照 ASCII 排序 我們可以直接判斷出正確答案為 sorting 次數為三 和 i 次數為二
這樣的需求我們也可以在 .Net 利用排序來達成,首先先對字典的 Value 做排序

dict = dict
.OrderByDescending(x => x.Value)
.ToDictionary(x => x.Key, y => y.Value);

Console.WriteLine(dict);

sorting	3
love	2
i	2
csharp	1

這時只要再對字典的KEY做一次排序就會得到結果了,這邊只要是做二次排序可以直接在 OrderByDescending 後面再接 ThenBy
最後在將拿出字典中最上方兩個字串值,即可獲得我們目標的資料

dict = dict
.OrderByDescending(x => x.Value)
.ThenBy(x => x.Key, StringComparer.Ordinal)
.ToDictionary(x => x.Key, y => y.Value)
.Take(2).Select(x => x.Key).ToList();

Console.WriteLine(dict);

sorting
i

也可以使用另一種寫法,可以先將字典的 Key 值建立成一個清單,不過這個清單還是未排序過得資料,我們可以在拿個這個清單去參考字典的資料進行排序

var result= new List<string>(dict.Keys);
Console.WriteLine(result);

love
i
csharp
sorting

這邊會先拿出兩個清單的元素之後去字典比比看 value 值是不是一樣
如果一樣就比較字母順序,如果不一樣就比較誰數字大

result.Sort((a, b) => dict[a] == dict[b] ? a.CompareTo(b) : freqMap[b].CompareTo(freqMap[a]));

Summary

今天學習了幾個排序常用的方法,須特別注意字串排序的部份,邏輯與數值排序不一樣並且 .Net 提供了多種寫法,可以挑選自己習慣的語法來使用