如何按指定规则高效比较字母数字混合字符串(Swift实现)
字母数字混合字符串比较逻辑实现优化
我会尝试用文字定义该问题,结合下方示例测试用例理解会更加直观:
"b" > "a" "3" > "1" "ac" > "ab" "32" > "25" "abcd1" > "abc2" "abc123a" > "abc2a" "abc123a" < "abc1234a" "abc123" < "abc123a" "abc12a49" > "abc12a39" "123ab3" = "123ab3" "ab12" > "12ab" "ab12" > "345"
核心需求
仅包含数字或仅包含字母的字符串比较逻辑十分简单,但二者混合时逻辑更复杂。核心规则为:将连续的数字组作为一个完整数值进行比较,而非逐字符对比单个数字字符。
现有实现
我目前采用暴力拆分法实现:先把字符串拆分为字母分组和数字分组,再逐组分别比较。该方案可正常运行,但性能不佳、实现不够优雅,希望了解是否有更优的实现方式。以下是可直接在Playground运行的完整依赖扩展与方法代码:
extension RangeReplaceableCollection { mutating func removeFirstSafe() -> Element? { guard !isEmpty else { return nil } return removeFirst() } } extension String { func split(grouping charSets: [[Character]]) -> [(CharacterType, String)] { var subStrings = [(CharacterType, String)]() var copy = self copy.__split(grouping: charSets, groupedSubstrings: &subStrings) return subStrings } mutating func __split(grouping charSets: [[Character]], groupedSubstrings: inout [(CharacterType, String)]) { guard let previousCharacter: Character = removeFirstSafe() else { return } var groupedSubString = String(previousCharacter) let prevCharSetGroup: CharacterType = charSets.indexOfCharSetGroupContainingCharacter(previousCharacter) while let currentCharacter = first, charSets.indexOfCharSetGroupContainingCharacter(currentCharacter) == prevCharSetGroup { groupedSubString.append(currentCharacter) removeFirst() } groupedSubstrings.append((prevCharSetGroup, groupedSubString)) __split(grouping: charSets, groupedSubstrings: &groupedSubstrings) } } enum CharacterType: Int, Comparable { case alphabet = 1 case number = 0 case unknown = -1 static func < (lhs: CharacterType, rhs: CharacterType) -> Bool { lhs.rawValue < rhs.rawValue } } extension Array where Element == [Character] { func indexOfCharSetGroupContainingCharacter(_ char: Character) -> CharacterType { for (index, group) in self.enumerated() { if group.contains(char) { return CharacterType(rawValue: index) ?? .unknown } } return .unknown } } extension Collection { subscript (safe index: Index) -> Element? { return indices.contains(index) ? self[index] : nil } } struct AlphanumericString { var string: String } func <(lhs: (CharacterType, String), rhs: (CharacterType, String)) -> Bool { if lhs.0 > rhs.0 { return false } else if lhs.0 < rhs.0 { return true } else { if lhs.0 == .alphabet || lhs.0 == .unknown { return lhs.1 < rhs.1 } else { return (Int(lhs.1) ?? 0) < (Int(rhs.1) ?? 0) } } } extension AlphanumericString: Comparable { static func < (lhs: AlphanumericString, rhs: AlphanumericString) -> Bool { if lhs.string == rhs.string { return false } let lhsGrouped = lhs.string.split(grouping: [Array("12345"), Array("abcde")]) let rhsGrouped = rhs.string.split(grouping: [Array("12345"), Array("abcde")]) for idx in lhsGrouped.indices { let lhsItem = lhsGrouped[idx] guard let rhsItem = rhsGrouped[safe: idx] else { return false } if lhsItem < rhsItem { return true } else if rhsItem < lhsItem { return false } } return true } } print(AlphanumericString(string: "abcd1") < AlphanumericString(string: "abc2"))
内容的提问来源于stack exchange,提问作者Aswath
相关产品推荐
相关产品推荐

