讓 Swift 的字串照數字規則比大小
Sep 2, 2018 · 4 min read
當字串的內容是數字,或是包含數字時,比大小的結果往往令我們失望,不是我們想要的。

如上圖所示,我們希望字串 “16” 比 “2” 大,但 “16” < “2” 的結果卻是 true。這是因為字串比較時預設是一個一個字 PK,所以會先比第一個字,因為 1 < 2,所以 “16” 小於 “2”。
若是字串內容都是數字,可以先將字串轉成數字,然後以我們熟悉的數字規則比大小。
let text1 = "16"let text2 = "2"if let number1 = Int(text1), let number2 = Int(text2) { print(number1 < number2)}
但是此方法有點麻煩,因為字串轉數字會變成 optional ,還要檢查是否轉換成功,而且只適用字串內容全是數字的情況。
其實搭配字串的 function compare(_:options:range:locale:),即可讓它照數字的規則比大小。
func compare<T>(_ aString: T, options mask: String.CompareOptions = default, range: Range<Self.Index>? = default, locale: Locale? = default) -> ComparisonResult where T : StringProtocolString.CompareOptions 型別的參數 mask 決定字串如何比大小,如果想像數字一樣比,可使用 String.CompareOptions.numeric。
範例
let text1 = "曲目16"let text2 = "曲目2"let result = text1.compare(text2, options: .numeric)if result == .orderedAscending { print("\(text2) > \(text1)")} else { print("\(text2) <= \(text1)")}
結果

compare 回傳結果的型別為 enum 定義的 ComparisonResult,有 orderedAscending(上升,前者小於後者),orderedSame(一樣),orderedDescending (下降,前者大於後者)三種 case。因此我們可從剛剛例子的 result 判斷誰大誰小。
此方法也可以使用在 array 的排序,例如以下例子
var songs = ["曲目16", "曲目2"]songs.sort { (text1, text2) -> Bool in return text1.compare(text2, options: .numeric) == .orderedAscending}songs

