如何在Groovy中实现类Excel式字母数字字符串排序?
Groovy实现Excel风格的字母数字排序
Excel的字母数字排序(自然排序)会将字符串中的连续数字视为整体数值比较,而非逐字符的字典序。要在Groovy中实现相同效果,需要自定义比较逻辑,替代默认a <=> b的字典序排序方式。
实现步骤与代码示例
- 拆分字符串为字母/数字片段:通过正则表达式将每个字符串拆分为连续的字母段和数字段。
- 自定义比较器:逐个对比两个字符串的对应片段,数字按数值比较,字母按字典序(默认不区分大小写,匹配Excel行为),字母段优先于数字段。
完整代码:
// 将字符串拆分为连续的字母和数字片段 def splitAlphanumeric(String s) { s.split(/(?<=\D)(?=\d)|(?<=\d)(?=\D)/) } // 待排序列表 def list = ["ADF1SD23GF12", "UTRR453FGT3", "NKUY43ERT5", "56GHY123", "MU157FGR234"] // 执行Excel风格排序 list.sort { a, b -> def partsA = splitAlphanumeric(a) def partsB = splitAlphanumeric(b) int minLength = Math.min(partsA.size(), partsB.size()) for (int i = 0; i < minLength; i++) { def partA = partsA[i] def partB = partsB[i] boolean isANumeric = partA.isNumber() boolean isBNumeric = partB.isNumber() int compareResult if (isANumeric && isBNumeric) { // 数字片段按数值大小比较 compareResult = partA.toLong() <=> partB.toLong() } else if (!isANumeric && !isBNumeric) { // 字母片段按不区分大小写的字典序比较(Excel默认行为) compareResult = partA.compareToIgnoreCase(partB) } else { // 字母片段排在数字片段之前 compareResult = isANumeric ? 1 : -1 } if (compareResult != 0) { return compareResult } } // 前缀完全匹配时,较短的字符串排在前面 partsA.size() <=> partsB.size() } // 输出排序结果 println list
自定义调整说明
- 如果需要区分大小写排序,将
compareToIgnoreCase替换为compareTo即可。 - 若字符串中包含超大数字(超出Long范围),可改用
BigDecimal进行数值比较。
内容的提问来源于stack exchange,提问作者Alexandr Sova
相关产品推荐
相关产品推荐

