.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 提供了多種寫法,可以挑選自己習慣的語法來使用