歡迎加入QQ討論群258996829
一葉知秋 頭像
蘋果2袋
2
一葉知秋

Swift 字符串速查表

發(fā)布時間:2016-01-04 22:47  回復(fù):0  查看:3126   最后回復(fù):2016-01-04 22:47  

Swift 的字符串 API 似乎讓人難以習(xí)慣。此外,每次 Swift 與其標(biāo)準(zhǔn)庫版本更新的時候,字符串的 API 也時不時會發(fā)生改變。你在 Stack Overflow 上尋找到的 Swift 1.2 解決方案往往不能在 Swift 2 上按照預(yù)期(甚至完全不能)使用。雖然從好的方面來看,我發(fā)現(xiàn)蘋果的官方文檔是非常有用的(參見本文底部的鏈接),但是出于備查的目的以及為了幫助仍掙扎于其中的人們,在此我仍舊了列出一系列的 String 代碼片段:

Gist 和我 Github 倉庫中的 Playground 都已提供)

字符串初始化

創(chuàng)建一個字符串對象有無數(shù)種方式可以使用,包括字面量、從其他 Swift 類型轉(zhuǎn)換、Unicode等等。

var emptyString = ""        // 空字符串
var stillEmpty = String()   // 另一種空字符串的形式
let helloWorld = "Hello World!" // 字符串字面量
let a = String(true)        // 由布爾值轉(zhuǎn)換為:"true"
let b: Character = "A"      // 顯式創(chuàng)建一個字符類型
let c = String(b)           // 從字符 "A" 轉(zhuǎn)換
let d = String(3.14)        // 從 Double 類型轉(zhuǎn)換為 "3.14"
let e = String(1000)        // 從 Int 類型轉(zhuǎn)換為 "1000"
let f = "Result = \(d)"     // 字符串插值 "Result = 3.14"
let g = "\u{2126}"          // Unicode 字符,歐米伽符號 Ω
let h = String(count:3, repeatedValue:b) // 重復(fù)字符組成的字符串 "AAA"

字符串是值類型

字符串是值類型(Value Type),當(dāng)用其賦值或者函數(shù)傳參的時候它會被拷貝(copied)。所拷貝的值在修改的時候是懶加載的(lazy)。

var aString = "Hello"
var bString = aString
bString += " World!"    // "Hello World!"
print("\(aString)")     // "Hello\n"

字符串檢測(空值、等值以及次序)

檢測一個字符串是否為空:

emptyString.isEmpty         // true
Swift 是支持 Unicode 編碼的,因此相等運算符("==")將會判斷 Unicode 的范式是否等價(canonical equivalence)。這意味著對于兩個字符串來說,如果擁有相同的語義(linguistic meaning)和表現(xiàn)形式的話,即使它們由不同 Unicode 標(biāo)量(scalar)組成,那么也認(rèn)為這兩個字符串相等:
let spain = "Espa?a"
let tilde = "\u{303}"
let country = "Espan" + "\(tilde)" + "a"
if country == spain {
  print("滿足匹配!")       // "滿足匹配!\n"
}
比較次序的話:
if "aaa" < "bbb" {
  print("aaa")
}

前綴/后綴檢測

檢測一個字符串是否擁有某個前綴或者后綴:

let line = "0001 這里放上一些測試數(shù)據(jù) %%%%"
line.hasPrefix("0001")    // true
line.hasSuffix("%%%%")    // true

大小寫互相轉(zhuǎn)換

顧名思義:

let mixedCase = "AbcDef"
let upper = mixedCase.uppercaseString // "ABCDEF"
let lower = mixedCase.lowercaseString // "abcdef"

字符集合

字符串并不是某種編碼的字符集合(collection views),但是它可以通過相應(yīng)的屬性為不同的編碼形式提供所對應(yīng)的字符集合。

country.characters       // characters
country.unicodeScalars   // Unicode scalar 21-bit codes
country.utf16            // UTF-16 編碼
country.utf8             // UTF-8 編碼

字符總數(shù)

字符串并沒有一個直接的屬性用以返回其包含的字符總數(shù),因為字符總數(shù)只對特定的編碼形式來說才有意義。因此,字符總數(shù)需要通過不同編碼的字符集合來訪問:

// spain = Espa?a
print("\(spain.characters.count)")      // 6
print("\(spain.unicodeScalars.count)")  // 6
print("\(spain.utf16.count)")           // 6
print("\(spain.utf8.count)")            // 7

使用索引來訪問字符集合

每個字符集合都擁有“索引”,可以通過它來訪問整個集合中的元素。這或許是在使用字符串過程中碰到的最大難點之一了。你不能使用下標(biāo)語法來訪問字符串中的任意元素(比如說string[5])。

要遍歷某個集合中的所有元素的時候(從現(xiàn)在開始我都將使用 characters 集合),可以通過 for...in 循環(huán)來進行:

var sentence = "Never odd or even"
for character in sentence.characters {
  print(character)
}

每個集合都有兩個實例屬性,你可以在集合中使用它們來進行索引,就如同下標(biāo)語法哪樣:

  • startIndex:返回首個元素的位置,如果為空,那么和 endIndex 的值相同。

  • endIndex:返回字符串逾尾(past the end)的位置。

注意到如果使用 endIndex 的話,就意味著你不能直接將其作為下標(biāo)來進行使用,因為這會導(dǎo)致越界。

let cafe = "café"
cafe.startIndex   // 0
cafe.endIndex     // 4 - 最后一個字符之后的位置
當(dāng)通過以下幾種方法進行字符串修改的時候,startIndex 和 endIndex 就變得極其有用:
  • successor():獲取下一個元素

  • predecessor():獲取上一個元素

  • advancedBy(n):向前或者向后跳 n 個元素

下面是一些用例,注意到如果必要的話你可以將操作串聯(lián)起來:

cafe[cafe.startIndex]                         // "c"
cafe[cafe.startIndex.successor()]             // "a"
cafe[cafe.startIndex.successor().successor()] // "f"
 
// 注意到 cafe[endIndex] 會引發(fā)運行時錯誤
cafe[cafe.endIndex.predecessor()]             // "é"
cafe[cafe.startIndex.advancedBy(2)]           // "f"
Indices 屬性將返回字符串中所有元素的范圍,這在遍歷集合的時候很有用:
for index in cafe.characters.indices {
  print(cafe[index])
}
你無法使用某個字符串中的索引來訪問另一個字符串。你可以通過 distanceTo 方法將索引轉(zhuǎn)換為整數(shù)值:
let word1 = "ABCDEF"
let word2 = "012345"
let indexC = word1.startIndex.advancedBy(2)
let distance = word1.startIndex.distanceTo(indexC) // 2
let digit = word2[word2.startIndex.advancedBy(distance)] // "2"

范圍的使用

要檢出字符串集合中某個范圍內(nèi)的元素的話,可以使用范圍。范圍可以通過 start 和 end 索引來完成創(chuàng)建:

let fqdn = "useyourloaf.com"
let rangeOfTLD = Range(start: fqdn.endIndex.advancedBy(-3), 
                         end: fqdn.endIndex)
let tld = fqdn[rangeOfTLD] // "com"
使用 "..." 或者 "..<" 運算符可以快速完成范圍的創(chuàng)建:
let rangeOfDomain = fqdn.startIndex..<fqdn.endIndex.advancedBy(-4)
let domain = fqdn[rangeOfDomain] // "useyourloaf"

通過索引或者范圍來截取字符串

要通過索引或者范圍來截取字符串的話,有許多方法:

var template = "<<<Hello>>>"
let indexStartOfText = template.startIndex.advancedBy(3)
let indexEndOfText = template.endIndex.advancedBy(-3)
let subString1 = template.substringFromIndex(indexStartOfText) // Hello>>>
let subString2 = template.substringToIndex(indexEndOfText)     // <<<Hello

let rangeOfHello = indexStartOfText..<indexEndOfText
// 下面這兩個方法都將返回字符串 "Hello"
let subString3 = template.substringWithRange(rangeOfHello)
let subString4 = template.substringWithRange(indexStartOfText..<indexEndOfText)

獲取前綴或者后綴

如果你需要得到或者拋棄字符串前面或者后面的某些元素的話,可以:

let digits = "0123456789"
let tail = String(digits.characters.dropFirst())  // "123456789"
let less = String(digits.characters.dropFirst(3)) // "23456789"
let head = String(digits.characters.dropLast(3))  // "0123456"
 
let prefix = String(digits.characters.prefix(2))  // "01"
let suffix = String(digits.characters.suffix(2))  // "89"
 
let index4 = digits.startIndex.advancedBy(4)
let thru4 = String(digits.characters.prefixThrough(index4)) // "01234"
let upTo4 = String(digits.characters.prefixUpTo(index4))    // "0123"
let from4 = String(digits.characters.suffixFrom(index4))    // "456789"

插入或刪除

要在指定位置插入字符的話,可以通過索引:

var stars = "******"
stars.insert("X", atIndex: stars.startIndex.advancedBy(3))
// "***X***"
要在索引出插入字符串的話,那么需要將字符串轉(zhuǎn)換為字符集:
stars.insertContentsOf("YZ".characters, at: stars.endIndex.advancedBy(-3))
// "***XYZ***"

范圍替換

要替換一個范圍的字符串內(nèi)容的話:

// "***XYZ***"
let xyzRange = stars.startIndex.advancedBy(3)..<stars.endIndex.advancedBy(-3)
stars.replaceRange(xyzRange, with: "ABC")
// "***ABC***"

添加元素

可以通過“+”運算符將字符串相互連接起來,也可以使用 appendContentsOf 方法:

var message = "Welcome"
message += " Tim" // "Welcome Tim"
message.appendContentsOf("!!!") // "Welcome Tim!!!

移除或者返回指定索引的元素

從一個字符串當(dāng)中移除某個元素,需要注意這個方法將會使該字符串此前所有的任何索引標(biāo)記(indice)失效:

var grades = "ABCDEF"
let ch = grades.removeAtIndex(grades.startIndex) // "A"
print(grades) // "BCDEF"

范圍移除

移除字符集中某個范圍的字符,需要主要的是這個方法同樣也會使索引標(biāo)記失效:

var sequences = "ABA BBA ABC"
let midRange = sequences.startIndex.advancedBy(4)...sequences.endIndex.advancedBy(-4)
sequences.removeRange(midRange)  // "ABA ABC"

與 NSString 橋接

String 可以轉(zhuǎn)換為 NSString 從而與 Objective-C 橋接。如果 Swift 標(biāo)準(zhǔn)庫沒有你所需要的功能的話,那么導(dǎo)入 Foundation 框架,通過 NSString 來訪問這些你所需要的方法。

請注意這個橋接方法并不是無損的,因此盡可能使用 Swift 標(biāo)準(zhǔn)庫完成大部分功能。

// 不要忘記導(dǎo)入 Foundation
import Foundation
let welcome = "hello world!"
welcome.capitalizedString     // "Hello World!"

檢索內(nèi)含的字符串

使用 NSString 方法的一個例子就是執(zhí)行內(nèi)含字符串的檢索:

let text = "123045780984"
if let rangeOfZero = text.rangeOfString("0",
       options: NSStringCompareOptions.BackwardsSearch) {
  // 尋找“0”元素,然后獲取之后的元素
  let suffix = String(text.characters.suffixFrom(rangeOfZero.endIndex)) // "984"
}

Playgournd

我發(fā)現(xiàn)在 Xcode 中通過 Playground 來熟悉 API 是一個非常好的選擇。如果你想要搶先體驗一下所有這些功能的話,這個文章的 Playground 可以從我的 Github 倉庫中下載。

拓展閱讀

原文:http://www.cocoachina.com/swift/20151218/14746.html

您還未登錄,請先登錄

熱門帖子

最新帖子

?