iOS中对存储范围字符串的数组进行排序的技术实现问题
解决范围字符串的数值排序问题
你遇到的问题很典型——默认的字符串排序是按字符的Unicode码点来比对的,完全不管字符串里的数值含义,所以肯定得不到你想要的按实际长度范围排序的结果。咱们得自定义排序规则,先从每个字符串里提取能代表它排序优先级的数值,再按这个数值来排序。
思路拆解
解析每个范围字符串:
- 对于
<X cm(或转义后的<X cm):取X作为基准,排序时让它比任何以X开头的范围都靠前,所以用X-1作为排序键 - 对于
X - Y cm:取范围的最小值X作为排序键,这样小范围会排在前面 - 对于
>X cm(或转义后的>X cm):取X作为基准,排序时让它比任何以X结尾的范围都靠后,所以用X+1作为排序键
- 对于
实现自定义排序函数:
先写一个辅助函数,帮我们把每个字符串转换成对应的排序键,然后用这个键来排序数组。
完整代码示例
// 辅助函数:提取每个范围字符串的排序键 func sortKey(for rangeString: String) -> Int { // 先处理转义字符和多余空格 let cleanedString = rangeString .replacingOccurrences(of: "<", with: "<") .replacingOccurrences(of: ">", with: ">") .trimmingCharacters(in: .whitespacesAndNewlines) // 处理小于类型的范围 if cleanedString.starts(with: "<") { let numberStr = cleanedString.components(separatedBy: CharacterSet.decimalDigits.inverted) .filter { !$0.isEmpty } .first ?? "" return (Int(numberStr) ?? 0) - 1 } // 处理大于类型的范围 else if cleanedString.starts(with: ">") { let numberStr = cleanedString.components(separatedBy: CharacterSet.decimalDigits.inverted) .filter { !$0.isEmpty } .first ?? "" return (Int(numberStr) ?? Int.max) + 1 } // 处理区间类型的范围 else if cleanedString.contains(" - ") { let parts = cleanedString.components(separatedBy: " - ") guard let firstPart = parts.first else { return Int.max } let numberStr = firstPart.components(separatedBy: CharacterSet.decimalDigits.inverted) .filter { !$0.isEmpty } .first ?? "" return Int(numberStr) ?? Int.max } // 解析失败的默认返回最大值,排在最后 return Int.max } // 你的原始数组 var arr = ["240 - 300 cm", "400 - 600 cm ", "90 - 130 cm", "<10 cm", ">700 cm"] // 用自定义规则排序 let sortedArr = arr.sorted { sortKey(for: $0) < sortKey(for: $1) } // 输出结果就是你想要的顺序:["<10 cm", "90 - 130 cm", "240 - 300 cm", "400 - 600 cm ", ">700 cm"]
关键细节说明
- 转义字符处理:如果你的数据库里存的是
<和>而不是</>,可以去掉replacingOccurrences那两行 - 空格处理:用
trimmingCharacters去掉字符串首尾的多余空格,避免因为末尾空格导致解析错误 - 容错处理:如果某个字符串格式异常(比如解析不出数字),会返回
Int.max,让它排在数组最后,不会影响正常数据的排序
把这个排序后的数组绑定到Table View的数据源,就能得到你想要的展示顺序啦~
内容的提问来源于stack exchange,提问作者skJosh
相关产品推荐
相关产品推荐

