2014-04-01 14 views
-2

我有下面的示例代碼:的Array.Sort與數字的字符串

List<string> test = new List<string>(); 
test.Add("Hello2"); 
test.Add("Hello1"); 
test.Add("Welcome2"); 
test.Add("World"); 
test.Add("Hello11"); 
test.Add("Hello10"); 
test.Add("Welcome0"); 
test.Add("World3"); 
test.Add("Hello100"); 
test.Add("Hello20"); 
test.Add("Hello3"); 

test.Sort(); 

但什麼發生的是,該test.Sort將數組排序:

"Hello1", 
"Hello10", 
"Hello100", 
"Hello11", 
"Hello2", 
"Hello20", 
"Hello3", 
"Welcome0", 
"Welcome2", 
"World", 
"World3" 

有什麼辦法來對它們進行排序所以string也會有正確的編號順序? (如果在string的末尾沒有數,即string總是先走 - 字母順序排列後)

預期輸出:

"Hello1", 
"Hello2", 
"Hello3", 
"Hello10", 
"Hello11", 
"Hello20", 
"Hello100", 
"Welcome0", 
"Welcome2", 
"World", 
"World3" 
+0

只是spitballing,但如果你想要「Hello1」來之前「Hello10」,你最好注入一個0,所以它會是「Hello01」,「Hello02」等。Windows資源管理器排序文件和文件夾在相同時尚,按字母順序完成。可能要查看字符串的最後2個字符,並確定它們是否都是**數字,如果不是,則以0爲前導。 – sab669

+0

@ sab669我不允許更改原始數據,它們非常重要對整個應用程序敏感。 –

回答

5

下面是使用LINQ一個可能的方式:

var orderedList = test 
      .OrderBy(x => new string(x.Where(char.IsLetter).ToArray())) 
      .ThenBy(x => 
      { 
       int number; 
       if (int.TryParse(new string(x.Where(char.IsDigit).ToArray()), out number)) 
        return number; 
       return -1; 
      }).ToList(); 
+1

它的工作原理!謝謝! –

+0

@ C.J。您的歡迎。注意,如果您的字符串在開頭或字母之間包含數字,這將無法按預期工作。僅當數字位於所有字母后面時才起作用。如果你想處理像這樣的不同情況讓我知道,我可以更新我的答案。 –

+1

+1不使用正則表達式來拆分字符串和數字,純粹依賴於LINQ。 – Habib

0

您可以使用LINQ與正則表達式相結合,以確保您只使用出現在字符串的結尾,可爲輔助排序

test 
    .Select(t => new{match = Regex.Match(t, @"\d+$"), val = t}) 
    .Select(x => new{sortVal = x.match.Success 
           ?int.Parse(x.match.Value) 
           :-1, 
        val = x.val}) 
    .OrderBy(x => x.val) 
    .ThenBy(x => x.sortVal) 
    .Select(x => x.val) 
    .ToList() 
1

創建一個IComparer<string>實現。這樣做的好處是可以通過LINQ建議來實現這一點,您現在可以將一個類傳遞給任何需要以此方式排序的類,而不是在其他位置重新創建該linq查詢。

這是特定於您從LIST調用排序。如果你要稱呼其爲Array.Sort()請看到兩個版本:

列表版本:

public class AlphaNumericComparer : IComparer<string> 
    { 
     public int Compare(string lhs, string rhs) 
     { 
      if (lhs == null) 
      { 
       return 0; 
      } 

      if (rhs == null) 
      { 
       return 0; 
      } 

      var s1Length = lhs.Length; 
      var s2Length = rhs.Length; 
      var s1Marker = 0; 
      var s2Marker = 0; 

      // Walk through two the strings with two markers. 
      while (s1Marker < s1Length && s2Marker < s2Length) 
      { 
       var ch1 = lhs[s1Marker]; 
       var ch2 = rhs[s2Marker]; 

       var s1Buffer = new char[s1Length]; 
       var loc1 = 0; 
       var s2Buffer = new char[s2Length]; 
       var loc2 = 0; 

       // Walk through all following characters that are digits or 
       // characters in BOTH strings starting at the appropriate marker. 
       // Collect char arrays. 
       do 
       { 
        s1Buffer[loc1++] = ch1; 
        s1Marker++; 

        if (s1Marker < s1Length) 
        { 
         ch1 = lhs[s1Marker]; 
        } 
        else 
        { 
         break; 
        } 
       } while (char.IsDigit(ch1) == char.IsDigit(s1Buffer[0])); 

       do 
       { 
        s2Buffer[loc2++] = ch2; 
        s2Marker++; 

        if (s2Marker < s2Length) 
        { 
         ch2 = rhs[s2Marker]; 
        } 
        else 
        { 
         break; 
        } 
       } while (char.IsDigit(ch2) == char.IsDigit(s2Buffer[0])); 

       // If we have collected numbers, compare them numerically. 
       // Otherwise, if we have strings, compare them alphabetically. 
       string str1 = new string(s1Buffer); 
       string str2 = new string(s2Buffer); 

       int result; 

       if (char.IsDigit(s1Buffer[0]) && char.IsDigit(s2Buffer[0])) 
       { 
        var thisNumericChunk = int.Parse(str1); 
        var thatNumericChunk = int.Parse(str2); 
        result = thisNumericChunk.CompareTo(thatNumericChunk); 
       } 
       else 
       { 
        result = str1.CompareTo(str2); 
       } 

       if (result != 0) 
       { 
        return result; 
       } 
      } 
      return s1Length - s2Length; 
     } 
    } 

調用就像這樣:

test.sort(new AlphaNumericComparer()); 

//RESULT 
Hello1 
Hello2 
Hello3 
Hello10 
Hello11 
Hello20 
Hello100 
Welcome0 
Welcome2 
World 
World3 

Array.sort版本:

創建類:

public class AlphaNumericComparer : IComparer 
{ 
    public int Compare(object x, object y) 
    { 
     string s1 = x as string; 
     if (s1 == null) 
     { 
      return 0; 
     } 
     string s2 = y as string; 
     if (s2 == null) 
     { 
      return 0; 
     } 

     int len1 = s1.Length; 
     int len2 = s2.Length; 
     int marker1 = 0; 
     int marker2 = 0; 

     // Walk through two the strings with two markers. 
     while (marker1 < len1 && marker2 < len2) 
     { 
      var ch1 = s1[marker1]; 
      var ch2 = s2[marker2]; 

      // Some buffers we can build up characters in for each chunk. 
      var space1 = new char[len1]; 
      var loc1 = 0; 
      var space2 = new char[len2]; 
      var loc2 = 0; 

      // Walk through all following characters that are digits or 
      // characters in BOTH strings starting at the appropriate marker. 
      // Collect char arrays. 
      do 
      { 
       space1[loc1++] = ch1; 
       marker1++; 

       if (marker1 < len1) 
       { 
        ch1 = s1[marker1]; 
       } 
       else 
       { 
        break; 
       } 
      } while (char.IsDigit(ch1) == char.IsDigit(space1[0])); 

      do 
      { 
       space2[loc2++] = ch2; 
       marker2++; 

       if (marker2 < len2) 
       { 
        ch2 = s2[marker2]; 
       } 
       else 
       { 
        break; 
       } 
      } while (char.IsDigit(ch2) == char.IsDigit(space2[0])); 

      // If we have collected numbers, compare them numerically. 
      // Otherwise, if we have strings, compare them alphabetically. 
      var str1 = new string(space1); 
      var str2 = new string(space2); 

      var result = 0; 

      if (char.IsDigit(space1[0]) && char.IsDigit(space2[0])) 
      { 
       var thisNumericChunk = int.Parse(str1); 
       var thatNumericChunk = int.Parse(str2); 
       result = thisNumericChunk.CompareTo(thatNumericChunk); 
      } 
      else 
      { 
       result = str1.CompareTo(str2); 
      } 

      if (result != 0) 
      { 
       return result; 
      } 
     } 
     return len1 - len2; 
    } 
} 

Call like so: 

This time test is an array instead of a list. 
Array.sort(test, new AlphaNumericComparer())