2017-08-21 70 views
1

我有一個列表,列表中的每個元素都是一個字符串,它包含特定格式的日期和整數:yyyyMMdd_number。C# - 如何排序列表字符串編號linq?

List<string> listStr = new List<string> { "20170822_10", "20170821_1", "20170823_4", "20170821_10", "20170822_11", "20170822_5", 
              "20170822_2", "20170821_3", "20170823_6", "20170823_21", "20170823_20", "20170823_2"}; 

當使用方法listStr.Sort();

結果如下:

20170821_1 
20170821_10 
20170821_3 
20170822_10 
20170822_11 
20170822_2 
20170822_5 
20170823_2 
20170823_20 
20170823_21 
20170823_4 
20170823_6

預期輸出:

20170821_1 
20170821_3 
20170821_10 
20170822_2 
20170822_5 
20170822_10 
20170822_11 
20170823_2 
20170823_4 
20170823_6 
20170823_20 
20170823_21

方式:我認爲每個串(DAY_NUMBER)將分裂用下劃線,然後比較和按數字排序。 但請建議我LINQ解決方案或更好的方法來排序在這種情況下。

回答

8

由於日期是在可字典順序進行排序的格式,你可以通過日期前綴使用字符串排序排序,並通過解析整數解決關係:

var sorted = listStr 
    .OrderBy(s => s.Split('_')[0]) 
    .ThenBy(s => int.Parse(s.Split('_')[1])); 

Demo.

+0

正是!感謝你的付出! +1 – Oosutsuke

2

我想象任何數字排序首先需要將該值轉換爲數字類型。所以你可以分割下劃線,按第一個值排序,然後按第二個值排序。事情是這樣的:

list.OrderBy(x => x.Split('_')[0]).ThenBy(x => int.Parse(x.Split('_')[1])) 

你可以,如果有必要改善這一點,通過創建一個類承擔其構造函數的字符串表示,提供的數字表示(與原來的字符串表示)作爲屬性。然後.Select()進入該類的列表並進行排序。這個類可以在內部做類型檢查,範圍檢查等上面

+0

我明白。感謝你的付出! +1 – Oosutsuke

1

答案是更容易跟蹤/理解,但純粹作爲學術興趣選擇,你可以做到以下幾點:

var sorted = listStr.OrderBy(x => Convert.ToInt32(x.Split('_')[0])*100 + Convert.ToInt32(x.Split('_')[1])); 

它的工作原理是,下劃線之後的後綴部分將小於100,並將字符串的兩個元素轉換爲一個整數,並保留相對的「大小」,然後對其進行排序。

其他兩種方法比較容易理解,但有一點我的替代方法是它只需要排序一次,所以會快一點(儘管我懷疑這對任何實際情況都很重要世界情景)。

+0

謝謝您的明確解釋!我學到了另外一種方法。 +1 – Oosutsuke