String 用 String.Index 取下標(biāo)(subscript)得到 Character,String.Index 要從 String 中獲取
成都地區(qū)優(yōu)秀IDC服務(wù)器托管提供商(創(chuàng)新互聯(lián)).為客戶提供專業(yè)的綿陽服務(wù)器托管,四川各地服務(wù)器托管,綿陽服務(wù)器托管、多線服務(wù)器托管.托管咨詢專線:18982081108let greeting = "Guten Tag!"greeting[greeting.startIndex] // Character "G"greeting[greeting.index(before: greeting.endIndex)] // Character "!"greeting[greeting.index(after: greeting.startIndex)] // Character "u"let index = greeting.index(greeting.startIndex, offsetBy: 7) greeting[index] // Character "a"String 用 Range<String.Index> 或 ClosedRange<String.Index> (以下 Range 和 ClosedRange 統(tǒng)稱為 Range) 取下標(biāo)得到 String
let str = "abc"str[str.startIndex..<str.index(after: str.startIndex)] // String "a"str[str.startIndex...str.index(after: str.startIndex)] // String "ab"String 通過 characters 屬性獲得 String.CharacterView,表示屏幕上顯示的內(nèi)容。String.CharacterView 通過 String.CharacterView.Index 取下標(biāo)得到 Character,String.CharacterView.Index 要從 String.CharacterView 中獲取
let str = "abc"let characters = str.characters // String.CharacterViewcharacters[characters.startIndex] // Character "a"注意,String.CharacterView 不遵循 RandomAccessCollection 協(xié)議,用 String.CharacterView.Index 取下標(biāo)不可以隨機(jī)訪問。另外,String.CharacterView.Index 與 String.Index 是相同的類型,屬于 Struct。String.Index 的文檔在 String 文檔下
typealias Index = String.CharacterView.IndexString.CharacterView 通過 Range<String.CharacterView.Index> 得到 String.CharacterView。用 Character 和 String.CharacterView 都可以生成 String
let str = "abc"let characters = str.characters // String.CharacterViewlet characters2 = characters[characters.startIndex..<characters.index(after: characters.startIndex)] // String.CharacterViewString(characters.first!) == String(characters2) // true. characters.first! is Character用 String.CharacterView 生成 Array<Character>,可以用 Int、Range<Int> 取下標(biāo)。用 Array<Character> 也可以生成 String
let str = "abc"let arr = Array(str.characters) // Array<Character> ["a", "b", "c"]arr[1] // Character "b"arr[1...2] // ArraySlice<Character> ["b", "c"]String(arr) // String "abc"Character 可以直接與 "a" 比較
let str = "abc"let a = str[str.startIndex] // Character "a"let b = str[str.index(str.startIndex, offsetBy: 1)] // Character "b"a == "a" // trueb > "a" // trueString 通過 utf8 屬性獲得 String.UTF8View,表示 UTF-8 編碼的內(nèi)容。String.UTF8View 通過 String.UTF8View.Index 取下標(biāo)得到 UTF8.CodeUnit,實(shí)際上是 UInt8;通過 Range<String.UTF8View.Index> 取下標(biāo)得到 String.UTF8View。String.UTF8View.Index 要從 String.UTF8View 中獲取。String.UTF8View 不遵循 RandomAccessCollection 協(xié)議,用 String.UTF8View.Index 取下標(biāo)不可以隨機(jī)訪問。用 String.UTF8View 生成 Array<UInt8>,可以用 Int、Range<Int> 取下標(biāo)。用 String.UTF8View 可以生成 String。用 UInt8 或 Array<UInt8> 也可以生成 String,但內(nèi)容表示數(shù)字或數(shù)字?jǐn)?shù)組,不是數(shù)字的 UTF-8 編碼內(nèi)容。
let str = "abc"let utf8 = str.utf8 // String.UTF8Viewlet n = utf8[utf8.startIndex] // UInt8 97let a = utf8[utf8.startIndex..<utf8.index(after: utf8.startIndex)] // String.UTF8View "a"let ab = utf8[utf8.startIndex...utf8.index(after: utf8.startIndex)] // String.UTF8View "ab"String(n) // "97", NOT "a"String(a) // "a"String(ab) // "ab"let arr = Array(utf8) // Array<UInt8> [97, 98, 99]let n2 = arr[0] // UInt8 97let arr2 = arr[0...1] // // ArraySlice<UInt8> [97, 98]String 通過 utf8CString 屬性獲得 ContiguousArray<CChar>,實(shí)際上是 ContiguousArray<Int8>,表示 UTF-8 編碼的內(nèi)容并且末尾增加一個(gè) 0,所以長度比 utf8 屬性的長度大 1。ContiguousArray<Int8> 可以用 Int、Range<Int> 取下標(biāo),分別得到 Int8 和 ArraySlice<Int8>。ContiguousArray 遵循 RandomAccessCollection 協(xié)議,用 Int 取下標(biāo)可以隨機(jī)訪問。
let str = "abc"let utf8 = str.utf8CString // ContiguousArray<Int8> [97, 98, 99, 0]let a = utf8[0] // Int8 97let ab = utf8[0...1] // ArraySlice<Int8> [97, 98]String 通過 utf16 屬性獲得 String.UTF16View,表示 UTF-16 編碼的內(nèi)容。String.UTF16View 通過 String.UTF16View.Index 取下標(biāo)得到 UTF16.CodeUnit,實(shí)際上是 UInt16;通過 Range<String.UTF16View.Index> 取下標(biāo)得到 String.UTF16View。String.UTF16View.Index 要從 String.UTF16View 中獲取。String.UTF16View 遵循 RandomAccessCollection 協(xié)議,用 String.UTF16View.Index 取下標(biāo)可以隨機(jī)訪問。用 String.UTF16View 生成 Array<UInt16>,可以用 Int、Range<Int> 取下標(biāo)。用 String.UTF16View 可以生成 String。用 UInt16 或 Array<UInt16> 也可以生成 String,但內(nèi)容表示數(shù)字或數(shù)字?jǐn)?shù)組,不是數(shù)字的 UTF-16 編碼內(nèi)容。
let str = "abc"let utf16 = str.utf16 // String.UTF16Viewlet n = utf16[utf16.startIndex] // UInt16 97let a = utf16[utf16.startIndex..<utf16.index(after: utf16.startIndex)] // String.UTF16View "a"let ab = utf16[utf16.startIndex...utf16.index(after: utf16.startIndex)] // String.UTF16View "ab"String(n) // "97", NOT "a"String(a) // "a"String(ab) // "ab"let arr = Array(utf16) // Array<UInt16> [97, 98, 99]let n2 = arr[0] // UInt16 97let arr2 = arr[0...1] // // ArraySlice<UInt8> [97, 98]對(duì) String、String.CharacterView、Array<Character>、String.UTF8View、Array<UInt8>、ContiguousArray<Int8>、String.UTF16View、Array<UInt16> 進(jìn)行判空(isEmpty)、獲取長度(count)、一個(gè)位置的取下標(biāo)([index])、一段距離的取下標(biāo)([range])測(cè)試,統(tǒng)計(jì)執(zhí)行時(shí)間。
定義測(cè)試類型、打印和更新時(shí)間的方法、要測(cè)試的 String
import Foundationenum TestType { case isEmpty case count case index case range }func printAndUpdateTime(_ date: inout Date) { let now = Date() print(now.timeIntervalSince(date)) date = now }let s = "aasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafcpiluioufnlkqjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjliopjktyuljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasderwytwghfsdfsdfgfdsg vrutj7edbj7 fdgotuyoergcwhmkl5lknjklqawkyrcqjljkljqjlqjhbrlqwfcbhafci luioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcvcnvbwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjkn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg iopiouvrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkfghngdljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmbkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqasdfsdwkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljdqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasddfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbsdfdsrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfsadfsdgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqsdfasjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdafgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlkasdfsdfsdfgfdsg vrutj7edbj7 ergcwhmkl5lknjklqawkrcqjljkljqjlqjhbrlqwfcbhafciluioufnlkjvjakjn fnvjalgkhlkdkjlk"測(cè)試代碼
let loopCount = 10000let index = s.characters.count / 2let testType: TestType = .rangeprint(testType)var date = Date() forLoop: for _ in 0..<loopCount { switch testType { case .isEmpty: _ = s.isEmpty case .count: break forLoop case .index: _ = s[s.index(s.startIndex, offsetBy: index)] case .range: let endIndex = s.index(s.startIndex, offsetBy: index) _ = s[s.startIndex..<endIndex] } }if testType == .count { date = Date() } else { print("String") printAndUpdateTime(&date) }let characters = s.charactersfor _ in 0..<loopCount { switch testType { case .isEmpty: _ = characters.isEmpty case .count: _ = characters.count case .index: _ = characters[characters.index(characters.startIndex, offsetBy: index)] case .range: let endIndex = characters.index(characters.startIndex, offsetBy: index) _ = characters[characters.startIndex..<endIndex] } }print("Characters") printAndUpdateTime(&date)let characterArr = Array(characters)for _ in 0..<loopCount { switch testType { case .isEmpty: _ = characterArr.isEmpty case .count: _ = characterArr.count case .index: _ = characterArr[index] case .range: _ = characterArr[0..<index] } }print("Characters array") printAndUpdateTime(&date)let utf8 = s.utf8for _ in 0..<loopCount { switch testType { case .isEmpty: _ = utf8.isEmpty case .count: _ = utf8.count case .index: _ = utf8[utf8.index(utf8.startIndex, offsetBy: index)] case .range: let endIndex = utf8.index(utf8.startIndex, offsetBy: index) _ = utf8[utf8.startIndex..<endIndex] } }print("UTF-8") printAndUpdateTime(&date)let utf8Arr = Array(utf8)for _ in 0..<loopCount { switch testType { case .isEmpty: _ = utf8Arr.isEmpty case .count: _ = utf8Arr.count case .index: _ = utf8Arr[index] case .range: _ = utf8Arr[0..<index] } }print("UTF-8 array") printAndUpdateTime(&date)let utf8CString = s.utf8CStringfor _ in 0..<loopCount { switch testType { case .isEmpty: _ = utf8CString.isEmpty case .count: _ = utf8CString.count case .index: _ = utf8CString[index] case .range: _ = utf8CString[0..<index] } }print("UTF-8 C string") printAndUpdateTime(&date)let utf16 = s.utf16for _ in 0..<loopCount { switch testType { case .isEmpty: _ = utf16.isEmpty case .count: _ = utf16.count case .index: _ = utf16[utf16.index(utf16.startIndex, offsetBy: index)] case .range: let endIndex = utf16.index(utf16.startIndex, offsetBy: index) _ = utf16[utf16.startIndex..<endIndex] } }print("UTF-16") printAndUpdateTime(&date)let utf16Arr = Array(utf16)for _ in 0..<loopCount { switch testType { case .isEmpty: _ = utf16Arr.isEmpty case .count: _ = utf16Arr.count case .index: _ = utf16Arr[index] case .range: _ = utf16Arr[0..<index] } }print("UTF-16 array") printAndUpdateTime(&date)測(cè)試結(jié)果
判空
獲取長度
一個(gè)位置的取下標(biāo)
一段距離的取下標(biāo)
以上比較中,判斷 String 是否為空,訪問 String 的 isEmpty 速度最快。對(duì)于其他操作,遵循 RandomAccessCollection 協(xié)議(ContiguousArray<Int8>、String.UTF16View 以及其他 Array)的類型效率較高。
進(jìn)一步比較判空操作
let loopCount = 10000var date = Date()for _ in 0..<loopCount { _ = s.isEmpty }print("isEmpty") printAndUpdateTime(&date)for _ in 0..<loopCount { _ = s == ""}print("== \"\"") printAndUpdateTime(&date)與訪問 String 的 isEmpty 相比,判斷 String 是否等于空 String 速度更快!
注意到文檔中,對(duì) String.UTF8View 和 String.UTF16View 的 Range 取下標(biāo)方法的說明
subscript(bounds: Range<String.UTF8View.Index>) -> String.UTF8View { get }subscript(bounds: Range<String.UTF16View.Index>) -> String.UTF16View { get }Complexity: O(n) if the underlying string is bridged from Objective-C, where n is the length of the string; otherwise, O(1).
如果 String 是從 Objective-C 的 NSString 橋接來的,時(shí)間復(fù)雜度為 O(n),否則為 O(1)。這句話怎么理解呢?前面說了,String.UTF8View 不遵循 RandomAccessCollection 協(xié)議,而 String.UTF16View 遵循 RandomAccessCollection 協(xié)議,兩者的時(shí)間復(fù)雜度應(yīng)該不同。這里怎么說時(shí)間復(fù)雜度與 String 是否橋接自 NSString 有關(guān)?以下進(jìn)一步探究。
let s2 = NSString(string: s) as Stringlet loopCount = 10000let index = s.characters.count / 2let index2 = s.characters.count - 1func test(_ s: String) { var date = Date() let utf8 = s.utf8 for _ in 0..<loopCount { _ = utf8[utf8.startIndex..<utf8.index(utf8.startIndex, offsetBy: index)] } print("UTF-8 index") printAndUpdateTime(&date) for _ in 0..<loopCount { _ = utf8[utf8.startIndex..<utf8.index(utf8.startIndex, offsetBy: index2)] } print("UTF-8 index2") printAndUpdateTime(&date) let utf16 = s.utf16 for _ in 0..<loopCount { _ = utf16[utf16.startIndex..<utf16.index(utf16.startIndex, offsetBy: index)] } print("UTF-16 index") printAndUpdateTime(&date) for _ in 0..<loopCount { _ = utf16[utf16.startIndex..<utf16.index(utf16.startIndex, offsetBy: index2)] } print("UTF-16 index2") printAndUpdateTime(&date) }print("String") test(s)print("\nString bridged from NSString") test(s2)測(cè)試結(jié)果
對(duì)比 index 與 index2 的差異。測(cè)試參數(shù) index2 約為 index 的 2 倍。UTF-8 index2 的耗時(shí)也約為 index 的 2 倍。UTF-16 的 index 和 index2 耗時(shí)相近。這與是否遵循 RandomAccessCollection 協(xié)議一致。
對(duì)比 String 與 NSString 的差異。橋接自 NSString 的 String 耗時(shí)比 String 要長,UTF-8 尤其明顯。這應(yīng)該就是文檔說明的情況。用 Range 取下標(biāo),橋接自 NSString 的 String,比 String 多一些操作,多出 O(n) 級(jí)別的時(shí)間,而不是取下標(biāo)的時(shí)間復(fù)雜度是 O(n)。
具體應(yīng)用時(shí),選取哪種編碼方式、取下標(biāo)方式?首先,編碼方式要看具體應(yīng)用場景。編碼方法不同,字符串的長度可能不同。如果字符串只含英文,比較好辦。如果字符串含有中文或 Emoji,選擇編碼方式就要慎重。注意,NSString 的 length 屬性獲得的長度對(duì)應(yīng) UTF-16 編碼。
let str = "abc"str.characters.count // 3str.unicodeScalars.count // 3str.utf16.count // 3(str as NSString).length // 3str.utf8.count // 3str.utf8CString.count - 1 // 3strlen(str) // 3let emojiStr = ""emojiStr.characters.count // 1emojiStr.unicodeScalars.count // 2emojiStr.utf16.count // 4(emojiStr as NSString).length // 4emojiStr.utf8.count // 8emojiStr.utf8CString.count - 1 // 8strlen(emojiStr) // 8let ChineseStr = "中文"ChineseStr.characters.count // 2ChineseStr.unicodeScalars.count // 2ChineseStr.utf16.count // 2(ChineseStr as NSString).length // 2ChineseStr.utf8.count // 6ChineseStr.utf8CString.count - 1 // 6strlen(ChineseStr) // 6另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
當(dāng)前文章:Swift中String取下標(biāo)及性能問題-創(chuàng)新互聯(lián)
分享鏈接:http://vcdvsql.cn/article6/gigog.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、電子商務(wù)、響應(yīng)式網(wǎng)站、微信公眾號(hào)、建站公司、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容