澳门至尊网站-首页

您的位置:澳门至尊网站 > 免费资源 > 取下标及品质难点

取下标及品质难点

2019-12-07 17:32

斯威夫特 中 String 取下标及质量难题

取下标

String

String 用 String.Index 取下标(subscript)得到 Character,String.Index 要从 String 中获取

let 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 统称为 Range卡塔尔 取下标拿到 String

let str = "abc"
str[str.startIndex..<str.index(after: str.startIndex)] // String "a"
str[str.startIndex...str.index(after: str.startIndex)] // String "ab"

Character

String 通过 characters 属性获得String.CharacterView,表示显示器上出示的剧情。String.CharacterView 通过 String.CharacterView.Index 取下标获得Character,String.CharacterView.Index 要从 String.CharacterView 中获得

let str = "abc"
let characters = str.characters // String.CharacterView
characters[characters.startIndex] // Character "a"

注意,String.CharacterView 不依照 RandomAccessCollection 公约,用 String.CharacterView.Index 取下标无法随意会见。另外,String.CharacterView.Index 与 String.Index 是意气风发律的花色,归属 Struct。String.Index 的文书档案在 String 文档下

typealias Index = String.CharacterView.Index

String.CharacterView 通过 Range<String.CharacterView.Index> 得到 String.CharacterView。用 Character 和 String.CharacterView 都可以生成 String

let str = "abc"
let characters = str.characters // String.CharacterView
let characters2 = characters[characters.startIndex..<characters.index(after: characters.startIndex)] // String.CharacterView
String(characters.first!) == String(characters2) // true. characters.first! is Character

用 String.CharacterView 生成 Array<Character>,可以用 Int、Range<Int> 取下标。用 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" // true
b > "a" // true

UTF-8

String 通过 utf8 属性获得 String.UTF8View,表示 UTF-8 编码的剧情。String.UTF8View 通过 String.UTF8View.Index 取下标得到UTF8.CodeUnit,实际上是 UInt8;通过 Range<String.UTF8View.Index> 取下标拿到 String.UTF8View。String.UTF8View.Index 要从 String.UTF8View 中拿走。String.UTF8View 不根据 RandomAccessCollection 公约,用 String.UTF8View.Index 取下标不能随便访谈。用 String.UTF8View 生成 Array<UInt8>,可以用 Int、Range<Int> 取下标。用 String.UTF8View 能够生成 String。用 UInt8 或 Array<UInt8> 也能够生成 String,但剧情表示数字或数字数组,不是数字的 UTF-8 编码内容。

let str = "abc"
let utf8 = str.utf8 // String.UTF8View
let n = utf8[utf8.startIndex] // UInt8 97
let 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 97
let arr2 = arr[0...1] // // ArraySlice<UInt8> [97, 98]

String 通过 utf8CString 属性拿到 孔蒂guousArray<CChar>,实际上是 ContiguousArray<Int8>,表示 UTF-8 编码的开始和结果还要最后扩大贰个0,所以长度比 utf8 属性的长度大 1。ContiguousArray<Int8> 能够用 Int、Range<Int> 取下标,分别获得 Int8 和 ArraySlice<Int8>。ContiguousArray 遵循 RandomAccessCollection 合同,用 Int 取下标能够恣心纵欲拜候。

let str = "abc"
let utf8 = str.utf8CString // ContiguousArray<Int8> [97, 98, 99, 0]
let a = utf8[0] // Int8 97
let ab = utf8[0...1] // ArraySlice<Int8> [97, 98]

UTF-16

String 通过 utf16 属性获得 String.UTF16View,表示 UTF-16 编码的剧情。String.UTF16View 通过 String.UTF16View.Index 取下标获得UTF16.CodeUnit,实际上是 UInt16;通过 Range<String.UTF16View.Index> 取下标拿到String.UTF16View。String.UTF16View.Index 要从 String.UTF16View 中得到。String.UTF16View 坚守 RandomAccessCollection 合同,用 String.UTF16View.Index 取下标能够自由拜访。用 String.UTF16View 生成 Array<UInt16>,可以用 Int、Range<Int> 取下标。用 String.UTF16View 能够生成 String。用 UInt16 或 Array<UInt16> 也得以生成 String,但内容表示数字或数字数组,不是数字的 UTF-16 编码内容。

let str = "abc"
let utf16 = str.utf16 // String.UTF16View
let n = utf16[utf16.startIndex] // UInt16 97
let 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 97
let arr2 = arr[0...1] // // ArraySlice<UInt8> [97, 98]

质量相比较

对 String、String.CharacterView、Array<Character>、String.UTF8View、Array<UInt8>、ContiguousArray<Int8>、String.UTF16View、Array<UInt16> 进行判空(isEmpty卡塔尔、获取长度(count卡塔尔、三个地方的取下标([index]卡塔尔(قطر‎、风姿洒脱段间隔的取下标([range]卡塔尔(قطر‎测量试验,总计施行时间。

概念测量检验项目、打字与印刷和修正时间的措施、要测量检验的 String

import Foundation

enum 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"

测量检验代码

let loopCount = 10000
let index = s.characters.count / 2
let testType: TestType = .range
print(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.characters
for _ 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.utf8
for _ 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.utf8CString
for _ 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.utf16
for _ 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)

测验结果

判空

图片 1

收获长度

图片 2

三个地方的取下标

图片 3

风度翩翩段间隔的取下标

图片 4

如上相比中,推断 String 是不是为空,访谈 String 的 isEmpty 速度最快。对于别的操作,坚守 RandomAccessCollection 左券(ContiguousArray<Int8>、String.UTF16View 以至其余Array卡塔尔(قطر‎的连串作用较高。

特别相比判空操作

let loopCount = 10000
var date = Date()

for _ in 0..<loopCount {
    _ = s.isEmpty
}

print("isEmpty")
printAndUpdateTime(&date)

for _ in 0..<loopCount {
    _ = s == ""
}

print("== """)
printAndUpdateTime(&date)

图片 5

与拜谒 String 的 isEmpty 相比较,剖断 String 是还是不是等于空 String 速度更加快!

注意到文书档案中,对 String.UTF8View 和 String.UTF16View 的 Range 取下标方法的验证

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 桥接来的,时间复杂度为 O(n卡塔尔,不然为 O(1卡塔尔(قطر‎。那句话怎么理解吧?前面说了,String.UTF8View 不遵循RandomAccessCollection 协议,而 String.UTF16View 服从RandomAccessCollection 协议,两个的小时复杂度应该例外。这里怎么说日子复杂度与 String 是还是不是桥接自 NSString 有关?以下进一层研讨。

let s2 = NSString(string: s) as String

let loopCount = 10000
let index = s.characters.count / 2
let index2 = s.characters.count - 1

func 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)

测量试验结果

图片 6

比较 index 与 index2 的异样。测量试验参数 index2 约为 index 的 2 倍。UTF-8 index2 的耗费时间也约为 index 的 2 倍。UTF-16 的 index 和 index2 耗时左近。那与是或不是比照 RandomAccessCollection 左券生龙活虎致。

比较之下 String 与 NSString 的出入。桥接自 NSString 的 String 耗费时间比 String 要长,UTF-8 特别显然。那应当便是文书档案表明的气象。用 Range 取下标,桥接自 NSString 的 String,比 String 多一些操作,多出 O(n)级其他时刻,实际不是取下标的光阴复杂度是 O(n卡塔尔(英语:State of Qatar)。

应用

切切实进行使时,选拔哪类编码情势、取下标格局?首先,编码格局要看具体应用处景。编码方法差异,字符串的尺寸恐怕两样。若是字符串只含克罗地亚语,相比较好办。借使字符串含有汉语或 Emoji,选取编码方式就要严慎。注意,NSString 的 length 属性获得的尺寸对应 UTF-16 编码。

let str = "abc"
str.characters.count // 3
str.unicodeScalars.count // 3
str.utf16.count // 3
(str as NSString).length // 3
str.utf8.count // 3
str.utf8CString.count - 1 // 3
strlen(str) // 3

let emojiStr = "
	  

本文由澳门至尊网站发布于免费资源,转载请注明出处:取下标及品质难点

关键词: