我在这里添加了这个问题的答案:Sorting List<String>
in C#,它要求一个自然的排序顺序,一个处理嵌入数字的顺序。
然而,我的实现是天真的,并且代替所有关于应用程序如何通过假设(土耳其测试任何人?)正确处理Unicode的帖子,我想我会请求帮助写一个更好的实现。或者,如果有.NET的内置方法,请告诉我:)
我对该问题中答案的实现只是通过字符串,逐个字符进行比较,直到遇到两个数字。然后它从两个字符串中提取连续的数字,这可能导致长度变化,用前导零填充最短的数字,然后进行比较。
然而,它存在问题。
例如,如果你在字符串x中有两个代码点一起构成字符È,但在另一个字符串中你只有一个代码点,那就是那个字符。
我的算法会失败,因为它会将变音符号码视为单个字符,并将其与其他字符串中的È进行比较。
任何人都可以指导我如何妥善处理这个问题吗?我希望支持指定一个CultureInfo
对象来处理语言问题,比如在德国比较“ss”和“ß”,以及类似的东西。
我认为我需要让我的代码枚举“真实字符”(我不知道真正的术语)而不是单个代码点。
对此有什么正确的解决方法?
此外,如果“自然”意味着“人类期望它的运作方式”,我会在思考时添加以下内容:
答案 0 :(得分:7)
这在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);
}
答案 1 :(得分:2)
我对.NET不太了解,但由于它也是一个算法问题,这是我的两分钱:
我尝试将字符串拆分为标记,可能使用正则表达式。然后,您可以使用适当的比较函数,根据令牌的类型,按令牌比较字符串令牌。
更具体地说:
使用正则表达式,如果你不使用[a-zA-Z]
但是正确的字符类如[:alpha:]
,也应该可以支持unicode。
对于不同形式的È的比较,你可以先尝试normalize字符串。