2014-03-12 32 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(); 
     } 
    } 
} 

然而,这一切都成为不必要的,如果你只需要改变你的字符串的格式前导零添加到所有数字部分。