排序格式不正确
本文关键字:不正确 格式 排序 | 更新日期: 2023-09-27 17:49:56
我有一个字符串数组,它包含像这样的文件名
1.Script_DBScript_03122014
我想对这个数组进行排序,所以我写了以下代码:
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");
您得到的结果是非常常见的字符串排序。您需要的是数字(或数字(排序。
在这种情况下,您可能需要解析字符串,从第一个点的左侧提取数字,使用int.Parse("string containing a number")
等方法,然后按整数排序。
我会这样做,但我不建议在不了解你做什么的情况下复制粘贴我的代码:
SQLScripts = SQLScripts
.OrderBy(T => int.Parse(T.Split('.')[0]))
.ToArray();
您需要所谓的"自然排序顺序"。
实际上,有一个名为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();
}
}
}
然而,如果您只是更改字符串的格式,将前导零添加到所有数字部分,那么这一切都将变得不必要。
您必须按.
分割字符串,并将数字部分解析为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[]
。