我有一个string[]
,其中每个元素都以一些数字值结尾.
string[] partNumbers = new string[]
{
"ABC10", "ABC1","ABC2", "ABC11","ABC10", "AB1", "AB2", "Ab11"
};
Run Code Online (Sandbox Code Playgroud)
我试图按如下方式对上面的数组进行排序,LINQ
但我没有得到预期的结果.
var result = partNumbers.OrderBy(x => x);
Run Code Online (Sandbox Code Playgroud)
实际结果:
AB1
Ab11
AB2
ABC1
ABC10
ABC10
ABC11
ABC2
预期结果
AB1
AB2
AB11
..
Nat*_*han 47
这是因为字符串的默认排序是标准字母数字字典(词典)排序,ABC11将在ABC2之前,因为排序总是从左到右进行.
要获得您想要的内容,您需要在order by子句中填充数字部分,例如:
var result = partNumbers.OrderBy(x => PadNumbers(x));
Run Code Online (Sandbox Code Playgroud)
哪里PadNumbers
可以定义为:
public static string PadNumbers(string input)
{
return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(10, '0'));
}
Run Code Online (Sandbox Code Playgroud)
对于输入字符串中出现的任何数字(或数字),这将填充零,以便OrderBy
看到:
ABC0000000010
ABC0000000001
...
AB0000000011
Run Code Online (Sandbox Code Playgroud)
填充仅发生在用于比较的密钥上.原始字符串(没有填充)将保留在结果中.
请注意,此方法假定输入中的数字的最大位数.
如果要使用LINQ和自定义比较器(如Dave Koelle的自定义比较器)按特定属性对对象列表进行排序,则应执行以下操作:
...
items = items.OrderBy(x => x.property, new AlphanumComparator()).ToList();
...
Run Code Online (Sandbox Code Playgroud)
您还必须更改Dave的类以从其继承,System.Collections.Generic.IComparer<object>
而不是基本继承,IComparer
因此类签名变为:
...
public class AlphanumComparator : System.Collections.Generic.IComparer<object>
{
...
Run Code Online (Sandbox Code Playgroud)
就我个人而言,我更喜欢James McCormack的实现,因为它实现了IDisposable,尽管我的基准测试表明它稍慢一些。
您可以使用PInvoke获得快速而良好的结果:
class AlphanumericComparer : IComparer<string>
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
static extern int StrCmpLogicalW(string s1, string s2);
public int Compare(string x, string y) => StrCmpLogicalW(x, y);
}
Run Code Online (Sandbox Code Playgroud)
您可以像AlphanumComparatorFast
上面的答案一样使用它。
归档时间: |
|
查看次数: |
30429 次 |
最近记录: |