2014-03-12 57 views
1

我有包含了像排序是不正確的格式

1.Script_DBScript_03122014 

我想排序這個數組,所以我寫了下面的代碼文件名的String數組:

Array.Sort(SQLScripts); 

但數組排序產生這樣的:

1.Script_DBScript(otherdetails)_03122014 
10.Script_DBScript(otherdetails)_03122014 
11.Script_DBScript(otherdetails)_03122014 
12.Script_DBScript(otherdetails)_03122014 
... 
2.Script_DBScript(otherdetails)_03122014 
20.Script_DBScript(otherdetails)_03122014 
21.Script_DBScript(otherdetails)_03122014 
22.Script_DBScript(otherdetails)_03122014 
... so on 

我怎樣才能在陣列中以下形式

1.Script_DBScript(otherdetails)_03122014 
2.Script_DBScript(otherdetails)_03122014 
3.Script_DBScript(otherdetails)_03122014 
4.Script_DBScript(otherdetails)_03122014 
5.Script_DBScript(otherdetails)_03122014 
... 
50.Script_DBScript(otherdetails)_03122014 

編輯: 代碼從目錄中檢索文件名:你得到

String[] SQLScripts = Directory.GetFiles(txtPath.Text, "*.sql"); 
+0

默認情況下,字符串按字母順序排序。這通常通過調整文件名來解決,例如, '0001.Script_DBScript_03122014'。這也是爲什麼一些文件名使用YYYYMMDD這樣的日期格式,即2014年3月13日的20140313,或同一天的2:57:01 PM的20140313_145701。 – Peter

+0

[自然排序順序在C#](http://stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp) – Oliver

+0

可能重複的一些實現看看[排序爲人類:自然排序順序](http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/) – Oliver

回答

2

你必須.分裂字符串和解析數字部分int,那麼你可以按數字排序。

你可以使用LINQ:

SQLScripts = SQLScripts 
    .Select(str => { 
     string[] split = str.Split('.'); 
     string numberPart = split[0].Trim(); 
     int i; 
     bool isNumber = int.TryParse(numberPart, out i); 
     int? number = isNumber ? i : (int?)null; 
     return new { str, split, numberPart, number }; 
    }) 
    .OrderByDescending(x => x.number.HasValue) 
    .ThenBy(x => x.number) 
    .Select(x => x.str) 
    .ToArray(); 

說明:

此查詢首先選擇一個匿名類型與所有相關的信息,然後將其訂單由Nullable<int>.HasValue屬性,它是表示一個布爾值是否第一令牌可能被解析爲int或不。由於true是「高於」false我已經使用OrderByDescending,因爲我想不可分析的字符串在底部。

之後(ThenBy)它將按數字排序以獲得數字順序而不是詞典。最後一步是從匿名類型中選擇字符串並使用ToArray獲取新的有序string[]

+0

執行代碼時沒有錯誤,但數組排序不正確,仍然得到相同的排序輸出。 –

+0

@RazoR:它已經過您的示例字符串測試並正確排序:1.Script_DBScript_03122014,2.Script_DBScript_03122014,10.Script_DBScript_03122014,11.Script_DBScript_03122014,12.Script_DBScript_03122014,20.Script_DBScript_03122014,21.Script_DBScript_03122014,22.Script_DBScript_03122014,22.Script_DBScript_03122014,.. 。' –

+0

其實,thr的DBScript名稱在每個索引中都有變化 –

3

結果是很常見的字符串排序。你需要的是數字(或數字)分類。

在這種情況下,您可能需要解析字符串,從第一個點的左側提取數字,使用某種方法(如int.Parse("string containing a number")),然後按整數進行排序。

我不喜歡這樣,但是我不建議複製粘貼我的代碼不理解你做什麼:

SQLScripts = SQLScripts 
    .OrderBy(T => int.Parse(T.Split('.')[0])) 
    .ToArray(); 
+0

錯誤 - 輸入字符串格式不正確。 –

+0

@RazoR我可以看看輸入字符串嗎? – AgentFire

+0

我編輯了我的問題... –

3

你需要什麼叫做「自然排列順序」。

實際上有一個名爲StrCmpLogicalW()的本機Windows API比較器,您可以使用它來執行此操作,並通過P/Invoke調用它。

你可以用它來編寫一個通用字符串比較器,然後你可以傳遞給Array.Sort()。這在很多情況下很有用,所以它可以添加到類庫中。

這裏有一個完整的編譯例子:

using System; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 
using System.Security; 

namespace ConsoleApp1 
{ 
    [SuppressUnmanagedCodeSecurity] 
    internal static class NativeMethods 
    { 
     [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] 
     public static extern int StrCmpLogicalW(string psz1, string psz2); 
    } 

    public sealed class NaturalStringComparer: IComparer<string> 
    { 
     public int Compare(string a, string b) 
     { 
      return NativeMethods.StrCmpLogicalW(a, b); 
     } 
    } 

    sealed class Program 
    { 
     void run() 
     { 
      string[] array = 
      { 
       "1.Script_DBScript_03122014", 
       "10.Script_DBScript_03122014", 
       "11.Script_DBScript_03122014", 
       "12.Script_DBScript_03122014", 
       "2.Script_DBScript_03122014", 
       "20.Script_DBScript_03122014", 
       "21.Script_DBScript_03122014", 
       "22.Script_DBScript_03122014" 
      }; 

      Array.Sort(array); // Sorts in the wrong order. 

      foreach (var filename in array) 
       Console.WriteLine(filename); 

      Console.WriteLine("\n"); 

      Array.Sort(array, new NaturalStringComparer()); // Sorts correctly. 

      foreach (var filename in array) 
       Console.WriteLine(filename); 
     } 

     static void Main(string[] args) 
     { 
      new Program().run(); 
     } 
    } 
} 

然而,這一切都成爲不必要的,如果你只需要改變你的字符串的格式前導零添加到所有數字部分。