我在这里添加了这个问题的答案:Sorting List<String>
in C#这需要一种自然的排序顺序,一种处理嵌入数字的顺序。
然而,我的实现是幼稚的,代替所有关于应用程序如何通过假设(土耳其测试任何人?)正确处理 Unicode 的帖子,我想我会寻求帮助编写更好的实现。或者,如果有.NET的内置方法,请告诉我:)
我对该问题的答案的实现只是遍历字符串,逐个字符地比较,直到在两者中都遇到一个数字。然后它从两个字符串中提取连续的数字,这可能会导致不同的长度,用前导零填充最短的数字,然后进行比较。
但是,它存在问题。
例如,如果您在字符串 x 中有两个代码点,它们一起构成字符 È,但在另一个字符串中您只有一个代码点,即那个字符。
我的算法会失败,因为它将变音符号代码点视为单个字符,并将其与另一个字符串中的 È 进行比较。
谁能指导我如何正确处理这个问题?我希望支持指定 CultureInfo
对象来处理语言问题,比如在德国比较“ss”和“ß”,以及类似的事情。
我想我需要让我的代码枚举“真实字符”(我不知道这里的真正术语)而不是单个代码点。
什么是正确的方法?
另外,如果“自然”的意思是“人类期望它工作的方式”,我会添加以下几点来思考:
最佳答案
这在 Windows 中已经可用, shell 在资源管理器窗口中排列文件时使用自然排序顺序。它使用的比较函数被导出并可用于任何程序,至少从 Windows 2000 开始。虽然 P/Invoke 不是最好的解决方案,但它确实具有相当大的优势,在过去的 10 多年里已经进行了数十亿次的测试。并以用户已经非常熟悉的方式对字符串进行排序。
处理变音符号已经是 .NET 的一部分,string.Normalize() 方法会处理它。
这是一个使用它的示例程序,它按照原始线程中的要求对字符串进行正确排序:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
class Program {
static void Main(string[] args) {
string[] arr = new string[] { "1", "5", "3", "6", "11", "9", "NUM1", "NUM0" };
Array.Sort(arr, new LogicalComparer());
foreach (string s in arr) Console.WriteLine(s);
Console.ReadLine();
}
}
class LogicalComparer : IComparer<string> {
public int Compare(string x, string y) {
return StrCmpLogicalW(x.Normalize(), y.Normalize());
}
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern int StrCmpLogicalW(string s1, string s2);
}
关于.net - 写一个更好的自然排序(比我的),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3717132/