.NET中不使用LINQ如何让SortedDictionary将"A-1"排在"A-10"前
问题根因
你当前遇到的排序异常是SortedDictionary默认使用字符串字典序比较导致的:该比较规则会逐字符比对字符的编码值,门牌号里的数字会被当成普通字符处理,所以会出现A-10排在A-1前面的不符合日常阅读习惯的结果,你需要的是按数字实际大小排序的自然排序规则。
解决方案
无需修改原有数据填充、遍历逻辑,也不需要使用LINQ,只要给SortedDictionary传入自定义的自然排序比较器即可,最简单的实现方式是调用Windows系统内置的StrCmpLogicalWAPI,该API原生支持自然排序规则,无需自行处理字符串拆分、数字转换等边缘场景,实现代码如下:
1. 实现自定义比较器
Imports System.Runtime.InteropServices Public Class NaturalStringComparer Implements IComparer(Of String) ' 调用系统内置的自然排序API <DllImport("shlwapi.dll", CharSet:=CharSet.Unicode)> Private Shared Function StrCmpLogicalW(psz1 As String, psz2 As String) As Integer End Function Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare Return StrCmpLogicalW(x, y) End Function End Class
2. 初始化SortedDictionary时传入比较器
' 仅需要修改这一行初始化代码,原有填充、遍历逻辑完全不变 Dim tenantDict As New SortedDictionary(Of String, String)(New NaturalStringComparer())
修改完成后遍历字典,输出顺序就是你需要的A-1、A-2、A-10、A-12的自然排序结果。
如果运行环境不允许调用系统API,可以自行实现比较逻辑:将门牌号按分隔符拆分为字符串前缀和数字部分,先比对前缀,前缀一致时将数字部分转为整型再比较大小即可,需要额外兼容格式不规范的门牌号场景。
内容的提问来源于stack exchange,提问作者Maury Markowitz
相关产品推荐
相关产品推荐

