如何在Kotlin中按数字而非字典序排序字母数字字符串?
Kotlin 实现自定义列表排序
默认的sort()方法采用字典序排序,所以会出现"10"排在"2"前、"A10"排在"A2"前的情况,这不符合你需要的纯数字按数值升序在前,字母开头的字符串按前缀字母升序+后续数字自然排序的需求。
解决方案:自定义比较器
通过实现Comparator来定义排序规则,核心逻辑是:
- 纯数字字符串优先排在前面,且按数值大小升序
- 非数字字符串先按前缀字母升序,前缀相同则纯字母排在带数字的前面,带数字的按数字数值升序
完整代码实现
// 存储拆分后的字符串部分:前缀(字母/非数字)、数字部分(如果有) data class StringPart(val prefix: String, val number: Long?) // 拆分字符串为前缀和数字部分的辅助函数 fun splitString(s: String): StringPart { val firstDigitIndex = s.indexOfFirst { it.isDigit() } return when { // 纯数字开头 firstDigitIndex == 0 -> { val lastDigitIndex = s.indexOfLast { it.isDigit() } StringPart("", s.substring(0, lastDigitIndex + 1).toLong()) } // 无数字,纯字母/其他字符 firstDigitIndex == -1 -> StringPart(s, null) // 前缀为字母,后面带数字 else -> { val prefix = s.substring(0, firstDigitIndex) val lastDigitIndex = s.indexOfLast { it.isDigit() } val numStr = s.substring(firstDigitIndex, lastDigitIndex + 1) StringPart(prefix, numStr.toLong()) } } } // 自定义排序比较器 val customSortComparator = Comparator<String> { a, b -> val partA = splitString(a) val partB = splitString(b) val isANumber = partA.prefix.isEmpty() && partA.number != null val isBNumber = partB.prefix.isEmpty() && partB.number != null when { // 数字排在非数字前面 isANumber && !isBNumber -> -1 !isANumber && isBNumber -> 1 // 两个都是数字,按数值比较 isANumber && isBNumber -> partA.number!!.compareTo(partB.number!!) // 非数字情况,先比前缀 else -> { val prefixCompare = partA.prefix.compareTo(partB.prefix) if (prefixCompare != 0) { prefixCompare } else { // 前缀相同,纯字母排在带数字的前面,数字按数值比较 when { partA.number == null && partB.number == null -> 0 partA.number == null -> -1 partB.number == null -> 1 else -> partA.number.compareTo(partB.number) } } } } } // 测试排序 fun main() { val list = mutableListOf("1", "2", "10", "A10", "A1", "A2", "B24C", "A") list.sortWith(customSortComparator) println(list) // 输出:[1, 2, 10, A, A1, A2, A10, B24C] }
逻辑说明
- 字符串拆分:将每个字符串拆分为前缀(字母或非数字部分)和数字部分(如果存在),方便后续比较。
- 优先级判断:纯数字字符串优先级最高,直接排在非数字字符串前面。
- 同类型比较:
- 纯数字之间按数值大小升序,避免字典序的问题。
- 非数字字符串先比较前缀字母,前缀相同则纯字母项排在带数字项前面,带数字项按数字数值升序排列。
内容的提问来源于stack exchange,提问作者Benjamin Ting
相关产品推荐
相关产品推荐

