Swift5.1 語言指南(六) 字符和字符串

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-pkdxqocj-er.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

是一系列字符,如的Swift字符串由類型表示能夠經過各類方式訪問a的內容,包括做爲的集合"hello, world""albatross"StringStringCharactergit

Swift StringCharacter類型提供了一種快速,符合Unicode的方式來處理代碼中的文本。字符串建立和操做的語法是輕量級和可讀的,字符串文字語法與C相似。字符串鏈接就像將兩個字符串與+運算符組合同樣簡單,字符串可變性經過在常量或變量之間進行選擇來管理,就像Swift中的任何其餘值同樣。您還可使用字符串將常量,變量,文字和表達式插入到更長的字符串中,這一過程稱爲字符串插值。這樣能夠輕鬆地爲顯示,存儲和打印建立自定義字符串值。github

儘管語法簡單,但Swift的String類型是一種快速,現代的字符串實現。每一個字符串都由與編碼無關的Unicode字符組成,並支持在各類Unicode表示中訪問這些字符。swift

注意api

Swift的String類型與Foundation的NSString是橋接的Foundation還擴展String爲公開定義的方法NSString這意味着,若是您導入Foundation,則能夠NSStringString不進行強制轉換的狀況下訪問這些方法數組

有關String與Foundation和Cocoa一塊兒使用的更多信息,請參閱字符串和NSString之間的橋接性能優化

字符串文字

您能夠String在代碼中包含預約義值做爲字符串文字字符串文字是由雙引號("包圍的字符序列微信

使用字符串文字做爲常量或變量的初始值:app

  1. let someString = "Some string literal value"

須要注意的是斯威夫特,推測型StringsomeString,由於它有一個字符串值初始化不變。ide

多行字符串文字

若是須要跨越多行的字符串,請使用多行字符串文字 - 由三個雙引號括起來的字符序列:

  1. let quotation = """
  2. The White Rabbit put on his spectacles. "Where shall I begin,
  3. please your Majesty?" he asked.
  4. "Begin at the beginning," the King said gravely, "and go on
  5. till you come to the end; then stop."
  6. """

多行字符串文字包括其開始和結束引號之間的全部行。該字符串從開始引號("""後面的第一行開始,到結束引號以前的行結束,這意味着下面的字符串都不會以換行符開頭或結尾:

  1. let singleLineString = "These are the same."
  2. let multilineString = """
  3. These are the same.
  4. """

當源代碼在多行字符串文字中包含換行符時,該換行符也會出如今字符串的值中。若是您想使用換行符來使源代碼更容易閱讀,可是您不但願換行符成爲字符串值的一部分,請在\這些行的末尾寫一個反斜槓():

  1. let softWrappedQuotation = """
  2. The White Rabbit put on his spectacles. "Where shall I begin, \
  3. please your Majesty?" he asked.
  4. "Begin at the beginning," the King said gravely, "and go on \
  5. till you come to the end; then stop."
  6. """

要建立以換行符開頭或結尾的多行字符串文字,請將空行寫爲第一行或最後一行。例如:

  1. let lineBreaks = """
  2. This string starts with a line break.
  3. It also ends with a line break.
  4. """

能夠縮進多行字符串以匹配周圍的代碼。在右引號mark("""以前的空格告訴Swift在全部其餘行以前要忽略哪些空格。可是,若是您在行的開頭寫入空格以及結束引號以前的空格,包含該空格

../_images/multilineStringWhitespace_2x.png

在上面的示例中,即便整個多行字符串文字是縮進的,字符串中的第一行和最後一行也不以任何空格開頭。中間線比縮進引號有更多的縮進,因此它從額外的四個空格縮進開始。

字符串文字中的特殊字符

字符串文字能夠包含如下特殊字符:

  • 轉義的特殊字符\0(空字符),\\(反斜槓),\t(水平製表符),\n(換行符),\r(回車符),\"(雙引號)和\'(單引號)
  • 任意的Unicode標值,寫爲\u{Ñ},其中Ñ是一個1-8位十六進制數(統一在討論的Unicode下文)

下面的代碼顯示了這些特殊字符的四個示例。wiseWords常數包含兩個逃脫雙引號。dollarSignblackHeartsparklingHeart常量展現Unicode標格式:

  1. let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
  2. // "Imagination is more important than knowledge" - Einstein
  3. let dollarSign = "\u{24}" // $, Unicode scalar U+0024
  4. let blackHeart = "\u{2665}" // ♥, Unicode scalar U+2665
  5. let sparklingHeart = "\u{1F496}" // 💖, Unicode scalar U+1F496

由於多行字符串文字使用三個雙引號而不是一個,因此您能夠"在多行字符串文字中包含雙引號()而不轉義它。要將文本包含"""在多行字符串中,請至少轉義其中一個引號。例如:

  1. let threeDoubleQuotationMarks = """
  2. Escaping the first quotation mark \"""
  3. Escaping all three quotation marks \"\"\"
  4. """

擴展字符串分隔符

您能夠將字符串文字放在擴展分隔符中,以在字符串中包含特殊字符,而不調用它們的效果。您將字符串放在引號(")中並用數字符號(#括起來例如,打印字符串文字會打印換行符轉義序列(),而不是將字符串打印到兩行。#"Line 1\nLine 2"#\n

若是須要字符串文字中字符的特殊效果,請匹配轉義字符(\後面的字符串中的數字符號數例如,若是您的字符串是而且您想要中斷該行,則能夠改成使用一樣,也打破了界限。#"Line 1\nLine 2"##"Line 1\#nLine 2"####"Line1\###nLine2"###

使用擴展分隔符建立的字符串文字也能夠是多行字符串文字。您可使用擴展分隔符將文本包含"""在多行字符串中,從而覆蓋結束文字的默認行爲。例如:

  1. let threeMoreDoubleQuotationMarks = #"""
  2. Here are three more double quotes: """
  3. """#

初始化空字符串

要建立空String值做爲構建更長字符串的起點,請將空字符串文字指定給變量,或String使用初始化程序語法初始化新實例:

  1. var emptyString = "" // empty string literal
  2. var anotherEmptyString = String() // initializer syntax
  3. // these two strings are both empty, and are equivalent to each other

String經過檢查其布爾isEmpty屬性來肯定是否爲空

  1. if emptyString.isEmpty {
  2. print("Nothing to see here")
  3. }
  4. // Prints "Nothing to see here"

字符串可變性

String能夠經過將特定分配給變量(在這種狀況下能夠修改)或常量(在這種狀況下不能修改)來指示特定是否能夠修改(或變異):

  1. var variableString = "Horse"
  2. variableString += " and carriage"
  3. // variableString is now "Horse and carriage"
  4. let constantString = "Highlander"
  5. constantString += " and another Highlander"
  6. // this reports a compile-time error - a constant string cannot be modified

注意

這種方法不一樣於Objective-C和Cocoa中的字符串變異,您能夠在兩個類(NSStringNSMutableString之間進行選擇,以指示字符串是否能夠變異。

字符串是值類型

Swift的String類型是值類型若是建立新String值,則在將String傳遞給函數或方法時,或者將其賦值給常量或變量時,將複製在每種狀況下,String都會建立現有值的新副本,並傳遞或分配新副本,而不是原始版本。結構和枚舉是值類型中描述了值類型

Swift的默認複製String行爲可確保當函數或方法爲您傳遞一個String值時,很明顯您擁有該確切的String值,不管它來自何處。除非您本身修改,不然您能夠確信傳遞的字符串不會被修改。

在幕後,Swift的編譯器優化了字符串的使用,所以只有在絕對必要的狀況下才會進行實際的複製。這意味着在使用字符串做爲值類型時,您總能得到出色的性能。

使用角色

您能夠經過使用循環遍歷字符串來訪問a的各個CharacterStringforin

  1. for character in "Dog!🐶" {
  2. print(character)
  3. }
  4. // D
  5. // o
  6. // g
  7. // !
  8. // 🐶

forin環中描述對於-在循環中

或者,您能夠Character經過提供Character類型註釋從單字符字符串文字建立獨立常量或變量

  1. let exclamationMark: Character = "!"

String能夠經過將Character數組做爲參數傳遞給其初始值設定項來構造值:

  1. let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
  2. let catString = String(catCharacters)
  3. print(catString)
  4. // Prints "Cat!🐱"

鏈接字符串和字符

String值能夠與加法運算符(一塊兒添加(或鏈接+)以建立新String值:

  1. let string1 = "hello"
  2. let string2 = " there"
  3. var welcome = string1 + string2
  4. // welcome now equals "hello there"

您還能夠使用加號賦值運算符(String附加到現有String變量+=

  1. var instruction = "look over"
  2. instruction += string2
  3. // instruction now equals "look over there"

您能夠使用類型的方法Character附加String變量Stringappend()

  1. let exclamationMark: Character = "!"
  2. welcome.append(exclamationMark)
  3. // welcome now equals "hello there!"

注意

您不能將a String附加Character到現有Character變量,由於Character值必須僅包含單個字符。

若是您使用多行字符串文字來構建較長字符串的行,則但願字符串中的每一行都以換行符結束,包括最後一行。例如:

  1. let badStart = """
  2. one
  3. two
  4. """
  5. let end = """
  6. three
  7. """
  8. print(badStart + end)
  9. // Prints two lines:
  10. // one
  11. // twothree
  12. let goodStart = """
  13. one
  14. two
  15. """
  16. print(goodStart + end)
  17. // Prints three lines:
  18. // one
  19. // two
  20. // three

在上面的代碼中,級聯badStartend產生兩行字符串,這是不指望的結果。由於最後一行badStart不以換行符結束,因此該行與第一行結合end相比之下,兩條線都goodStart以一條換結束,因此當它與end結果結合時有三條線,正如預期的那樣。

字符串插值

字符串插值是一種String經過在字符串文字中包含它們的值,從常量,變量,文字和表達式的混合構造新的方法您能夠在單行和多行字符串文字中使用字符串插值。插入到字符串文字中的每一個項目都包含在一對括號中,前綴爲反斜槓(\):

  1. let multiplier = 3
  2. let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
  3. // message is "3 times 2.5 is 7.5"

在上面的示例中,值的值multiplier插入到字符串文字中\(multiplier)此佔位符將替換multiplier爲評估字符串插值以建立實際字符串時的實際值

multiplier也是字符串中較大表達式的一部分。此表達式計算值,並將result()插入到字符串中。在這種狀況下,表達式被寫爲當它包含在字符串文字中時。Double(multiplier) 2.57.5\(Double(multiplier) 2.5)

您可使用擴展字符串分隔符來建立包含字符的字符串,不然這些字符將被視爲字符串插值。例如:

  1. print(#"Write an interpolated string in Swift using \(multiplier)."#)
  2. // Prints "Write an interpolated string in Swift using \(multiplier)."

要在使用擴展分隔符的字符串中使用字符串插值,請將反斜槓前面的數字符號數與字符串開頭和結尾處的數字符號數相匹配。例如:

  1. print(#"6 times 7 is \#(6 * 7)."#)
  2. // Prints "6 times 7 is 42."

注意

您在插值字符串內的括號內寫的表達式不能包含未轉義的反斜槓(\),回車符或換行符。可是,它們能夠包含其餘字符串文字。

統一

Unicode是用於在不一樣書寫系統中編碼,表示和處理文本的國際標準。它使您可以以標準化形式表示來自任何語言的幾乎任何字符,並從外部源(如文本文件或網頁)讀取和寫入這些字符。Swift StringCharacter類型徹底符合Unicode,如本節所述。

Unicode標量值

在幕後,Swift的原生String類型是根據Unicode標量值構建的Unicode標量值是字符或修飾符的惟一21位數字,例如U+0061for )或for )。LATIN SMALL LETTER A"a"U+1F425FRONT-FACING BABY CHICK"🐥"

請注意,並不是全部21位Unicode標量值都分配給字符 - 某些標量保留用於未來分配或用於UTF-16編碼。已分配給一個字符標量值一般還具備一個名字,如在上面的實施例。LATIN SMALL LETTER AFRONT-FACING BABY CHICK

擴展的Grapheme集羣

Swift Character類型的每一個實例都表明一個擴展的字形集羣擴展字形集羣是一個或多個Unicode標量的序列(當組合時)產生單我的類可讀字符。

這是一個例子。該字母é能夠表示爲單個Unicode標量é,或)。可是,同一個字母也能夠表示爲一標量 - 標準字母,或),後跟標量()。標量圖形應用到它前面,把一個標量時它是由一個支持Unicode的文本的渲染系統渲染。LATIN SMALL LETTER WITH ACUTEU+00E9eLATIN SMALL LETTER EU+0065COMBINING ACUTE ACCENTU+0301COMBINING ACUTE ACCENTeé

在這兩種狀況下,字母é都表示爲單個Swift Character值,表示擴展的字形集羣。在第一種狀況下,集羣包含單個標量; 在第二種狀況下,它是兩個標量的集羣:

  1. let eAcute: Character = "\u{E9}" // é
  2. let combinedEAcute: Character = "\u{65}\u{301}" // e followed by ́
  3. // eAcute is é, combinedEAcute is é

擴展的字形集羣是將許多複雜的腳本字符表示爲單個Character的靈活方式例如,韓語字母表中的韓語音節能夠表示爲預先組合或分解的序列。這兩個表示都符合CharacterSwift中的單個值:

  1. let precomposed: Character = "\u{D55C}" // 한
  2. let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
  3. // precomposed is 한, decomposed is 한

擴展的字形集羣使標量能夠封閉標記(例如,或)以將其餘Unicode標量做爲單個值的一部分包含在內COMBINING ENCLOSING CIRCLEU+20DDCharacter

  1. let enclosedEAcute: Character = "\u{E9}\u{20DD}"
  2. // enclosedEAcute is é⃝

區域指標符號的Unicode標量能夠成對組合以造成單個Character值,例如)和)的這種組合REGIONAL INDICATOR SYMBOL LETTER UU+1F1FAREGIONAL INDICATOR SYMBOL LETTER SU+1F1F8

  1. let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
  2. // regionalIndicatorForUS is 🇺🇸

計算字符

要檢索Character字符串中值的計數,請使用字符串的count屬性:

  1. let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
  2. print("unusualMenagerie has \(unusualMenagerie.count) characters")
  3. // Prints "unusualMenagerie has 40 characters"

請注意,Swift將擴展字形集合用於Character值意味着字符串鏈接和修改可能並不老是會影響字符串的字符數。

例如,若是使用四個字符的單詞初始化一個新字符串cafe,而後在字符串的末尾附加一個),則結果字符串的字符數仍爲第四個字符,而不是COMBINING ACUTE ACCENTU+03014e

  1. var word = "cafe"
  2. print("the number of characters in \(word) is \(word.count)")
  3. // Prints "the number of characters in cafe is 4"
  4. word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301
  5. print("the number of characters in \(word) is \(word.count)")
  6. // Prints "the number of characters in café is 4"

注意

擴展的字形集羣能夠由多個Unicode標量組成。這意味着不一樣的字符和相同字符的不一樣表示可能須要不一樣的內存量來存儲。所以,Swift中的字符不會在字符串表示中佔用相同數量的內存。所以,若是不迭代字符串以肯定其擴展的字形集羣邊界,則沒法計算字符串中的字符數。若是使用特別長的字符串值,請注意該count屬性必須遍歷整個字符串中的Unicode標量,以肯定該字符串的字符。

count屬性返回的字符數不老是與包含相同字符length屬性NSString相同。a的長度NSString基於字符串的UTF-16表示中的16位代碼單元的數量,而不是字符串中Unicode擴展的字形集羣的數量。

訪問和修改字符串

您能夠經過其方法和屬性或使用下標語法來訪問和修改字符串。

字符串索引

每一個String值都有一個關聯的索引類型String.Index它對應Character於字符串中每一個的位置

如上所述,不一樣的字符可能須要不一樣的內存量來存儲,所以爲了肯定哪一個Character位於特定位置,您必須從開頭或結尾迭代每一個Unicode標量String所以,Swift字符串不能用整數值索引。

使用該startIndex屬性訪問第Character一個的位置StringendIndex屬性是a中最後一個字符後的位置String所以,該endIndex屬性不是字符串下標的有效參數。若是a String是空的,startIndex而且endIndex是相等的。

您可使用index(before:)index(after:)方法訪問給定索引以前和以後的索引String要訪問遠離給定索引的索引,可使用該index(_:offsetBy:)方法而不是屢次調用其中一種方法。

您可使用下標語法來訪問Character特定String索引。

  1. let greeting = "Guten Tag!"
  2. greeting[greeting.startIndex]
  3. // G
  4. greeting[greeting.index(before: greeting.endIndex)]
  5. // !
  6. greeting[greeting.index(after: greeting.startIndex)]
  7. // u
  8. let index = greeting.index(greeting.startIndex, offsetBy: 7)
  9. greeting[index]
  10. // a

嘗試訪問字符串範圍Character以外的索引或字符串範圍以外的索引將觸發運行時錯誤。

  1. greeting[greeting.endIndex] // Error
  2. greeting.index(after: greeting.endIndex) // Error

使用該indices屬性能夠訪問字符串中單個字符的全部索引。

  1. for index in greeting.indices {
  2. print("\(greeting[index]) ", terminator: "")
  3. }
  4. // Prints "G u t e n T a g ! "

注意

您可使用startIndexendIndex屬性和index(before:)index(after:)以及index(_:offsetBy:)對符合任何類型的方法Collection的協議。這包括String,以下圖所示,以及集合類型,如ArrayDictionarySet

插入和刪除

要將單個字符插入到指定索引處的字符串中,請使用該insert(_:at:)方法,並在指定索引處插入另外一個字符串的內容,請使用該insert(contentsOf:at:)方法。

  1. var welcome = "hello"
  2. welcome.insert("!", at: welcome.endIndex)
  3. // welcome now equals "hello!"
  4. welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
  5. // welcome now equals "hello there!"

要從指定索引處的字符串中刪除單個字符,請使用該remove(at:)方法,並刪除指定範圍內的子字符串,請使用如下removeSubrange(_:)方法:

  1. welcome.remove(at: welcome.index(before: welcome.endIndex))
  2. // welcome now equals "hello there"
  3. let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
  4. welcome.removeSubrange(range)
  5. // welcome now equals "hello"

注意

您可使用insert(_:at:)insert(contentsOf:at:)remove(at:),和removeSubrange(_:)對符合任何類型的方法RangeReplaceableCollection的協議。這包括String,以下圖所示,以及集合類型,如ArrayDictionarySet

從字符串中獲取子字符串時 - 例如,使用下標或相似方法prefix(_:)- 結果是一個實例Substring,而不是另外一個字符串。Swift中的子字符串與字符串具備大多數相同的方法,這意味着您能夠像處理字符串同樣使用子字符串。可是,與字符串不一樣,您在對字符串執行操做時僅使用子字符串很短的時間。當您準備好將結果存儲更長時間時,將子字符串轉換爲實例String例如:

  1. let greeting = "Hello, world!"
  2. let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
  3. let beginning = greeting[..<index]
  4. // beginning is "Hello"
  5. // Convert the result to a String for long-term storage.
  6. let newString = String(beginning)

與字符串同樣,每一個子字符串都有一個內存區域,用於存儲構成子字符串的字符。字符串和子字符串之間的區別在於,做爲性能優化,子字符串能夠重用用於存儲原始字符串的部份內存,或者用於存儲另外一個子字符串的內存的一部分。(字符串具備相似的優化,但若是兩個字符串共享內存,則它們是相等的。)此性能優化意味着在修改字符串或子字符串以前,您沒必要支付複製內存的性能成本。如上所述,子串不適合長期存儲 - 由於它們重用原始字符串的存儲,只要使用任何子字符串,整個原始字符串就必須保存在內存中。

在上面的示例中,greeting是一個字符串,這意味着它有一個內存區域,其中存儲了構成字符串的字符。由於beginning是子串greeting,因此它重用了使用的內存greeting相反,newString是一個字符串 - 當它從子字符串建立時,它有本身的存儲空間。下圖顯示了這些關係:

../_images/stringSubstring_2x.png

注意

兩者StringSubstring符合StringProtocol協議,這意味着它的常方便的字符串操做函數接受StringProtocol的值。您可使用a StringSubstring調用此類函數

比較字符串

Swift提供了三種比較文本值的方法:字符串和字符相等,前綴相等和後綴相等。

字符串和字符平等

字符串和字符平等與「等於」運算符(檢查==)和「不等於」運算符(!=),如在比較操做符

  1. let quotation = "We're a lot alike, you and I."
  2. let sameQuotation = "We're a lot alike, you and I."
  3. if quotation == sameQuotation {
  4. print("These two strings are considered equal")
  5. }
  6. // Prints "These two strings are considered equal"

若是兩個String值(或兩個Character值)的擴展字形簇在規範上等效,則它們被認爲是相等的若是擴展的字形集羣具備相同的語言含義和外觀,則它們在規範上是等效的,即便它們是由幕後的不一樣Unicode標量組成的。

例如,)在規範上等效於)後跟)。這兩個擴展的字形集合都是表示字符的有效方式,所以它們被認爲是規範等價的:LATIN SMALL LETTER WITH ACUTEU+00E9LATIN SMALL LETTER EU+0065COMBINING ACUTE ACCENTU+0301é

  1. // "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE
  2. let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
  3. // "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
  4. let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
  5. if eAcuteQuestion == combinedEAcuteQuestion {
  6. print("These two strings are considered equal")
  7. }
  8. // Prints "These two strings are considered equal"

相反,),如英語中所使用的,並不等同於俄語中使用的,或)。角色在視覺上類似,但不具備相同的語言含義:LATIN CAPITAL LETTER AU+0041"A"CYRILLIC CAPITAL LETTER AU+0410"А"

  1. let latinCapitalLetterA: Character = "\u{41}"
  2. let cyrillicCapitalLetterA: Character = "\u{0410}"
  3. if latinCapitalLetterA != cyrillicCapitalLetterA {
  4. print("These two characters are not equivalent.")
  5. }
  6. // Prints "These two characters are not equivalent."

注意

Swift中的字符串和字符比較不是區域設置敏感的。

前綴和後綴相等

要檢查字符串是否具備特定字符串前綴或後綴,請調用字符串hasPrefix(_:)hasSuffix(_:)方法,二者都採用類型的單個參數String並返回布爾值。

下面的例子考慮了一組字符串,這些字符串表明了莎士比亞的「 羅密歐與朱麗葉 」前兩部劇中的場景位置

  1. let romeoAndJuliet = [
  2. "Act 1 Scene 1: Verona, A public place",
  3. "Act 1 Scene 2: Capulet's mansion",
  4. "Act 1 Scene 3: A room in Capulet's mansion",
  5. "Act 1 Scene 4: A street outside Capulet's mansion",
  6. "Act 1 Scene 5: The Great Hall in Capulet's mansion",
  7. "Act 2 Scene 1: Outside Capulet's mansion",
  8. "Act 2 Scene 2: Capulet's orchard",
  9. "Act 2 Scene 3: Outside Friar Lawrence's cell",
  10. "Act 2 Scene 4: A street in Verona",
  11. "Act 2 Scene 5: Capulet's mansion",
  12. "Act 2 Scene 6: Friar Lawrence's cell"
  13. ]

您可使用數組中hasPrefix(_:)方法romeoAndJuliet來計算播放的第1幕中的場景數量:

  1. var act1SceneCount = 0
  2. for scene in romeoAndJuliet {
  3. if scene.hasPrefix("Act 1 ") {
  4. act1SceneCount += 1
  5. }
  6. }
  7. print("There are \(act1SceneCount) scenes in Act 1")
  8. // Prints "There are 5 scenes in Act 1"

一樣,使用該hasSuffix(_:)方法計算在Capulet的豪宅和Friar Lawrence的單元格內或周圍發生的場景數量:

  1. var mansionCount = 0
  2. var cellCount = 0
  3. for scene in romeoAndJuliet {
  4. if scene.hasSuffix("Capulet's mansion") {
  5. mansionCount += 1
  6. } else if scene.hasSuffix("Friar Lawrence's cell") {
  7. cellCount += 1
  8. }
  9. }
  10. print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
  11. // Prints "6 mansion scenes; 2 cell scenes"

注意

hasPrefix(_:)hasSuffix(_:)在每個串的方法執行所述擴展字形簇之間的字符逐字符規範等價比較,如在所述的字符串和字符平等

字符串的Unicode表示

將Unicode字符串寫入文本文件或其餘存儲時,該字符串中的Unicode標量將以多種Unicode定義的編碼形式之一進行編碼每一個表單都以小塊(稱爲代碼單元)對字符串進行編碼這些包括UTF-8編碼格式(將字符串編碼爲8位代碼單元),UTF-16編碼格式(將字符串編碼爲16位代碼單元)和UTF-32編碼格式(對其進行編碼)字符串爲32位代碼單元)。

Swift提供了幾種不一樣的方法來訪問字符串的Unicode表示。您可使用forin語句迭代字符串,以CharacterUnicode擴展字形集羣的形式訪問其各個值。使用字符中描述了此過程

或者,訪問String其餘三個符合Unicode的表示之一中值:

  • UTF-8代碼單元的集合(使用字符串的utf8屬性訪問
  • UTF-16代碼單元的集合(使用字符串的utf16屬性訪問
  • 一組21位Unicode標量值,至關於字符串的UTF-32編碼形式(使用字符串的unicodeScalars屬性訪問

下面各實施例中示出了下面的字符串,它是由所述字符的向上的不一樣表示Dog或Unicode標),以及🐶字符(或Unicode標):DOUBLE EXCLAMATION MARKU+203CDOG FACEU+1F436

  1. let dogString = "Dog‼🐶"

UTF-8表示法

您能夠String經過迭代其utf8屬性來訪問a的UTF-8表示此屬性的類型String.UTF8View是無符號8位(UInt8)值的集合,對於字符串的UTF-8表示形式,每一個字節對應一個值:

../_images/UTF8_2x.png
  1. for codeUnit in dogString.utf8 {
  2. print("\(codeUnit) ", terminator: "")
  3. }
  4. print("")
  5. // Prints "68 111 103 226 128 188 240 159 144 182 "

在上面的例子中,前三個十進制codeUnit值(68111103)所表示的字符Dog,其UTF-8表示相同的ASCII表示。接下來的三個十進制codeUnit值(226128188)是一個三字節UTF-8表示的字符。最後四個值()是一個四字節UTF-8表示的字符。DOUBLE EXCLAMATION MARKcodeUnit240159144182DOG FACE

UTF-16表示法

您能夠String經過迭代其utf16屬性來訪問a的UTF-16表示此屬性的類型String.UTF16View是無符號16位(UInt16)值的集合,對於字符串的UTF-16表示形式,每一個16位代碼單元對應一個值:

../_images/UTF16_2x.png
  1. for codeUnit in dogString.utf16 {
  2. print("\(codeUnit) ", terminator: "")
  3. }
  4. print("")
  5. // Prints "68 111 103 8252 55357 56374 "

再次,前三個codeUnit值(68111103)所表示的字符Dog,其UTF-16代碼單元具備如在字符串的UTF-8表示相同的值(由於這些Unicode標量表示ASCII字符)。

第四codeUnit值(8252)是十六進制值的十進位等值203C,它表明了Unicode標U+203C字符。此字符能夠表示爲UTF-16中的單個代碼單元。DOUBLE EXCLAMATION MARK

第五和第六個codeUnit值(5535756374)是字符的UTF-16代理對錶示這些值的高代理值(十進制值)和一個低代理值(十進制值)。DOG FACEU+D83D55357U+DC3656374

Unicode標量表示

您能夠String經過迭代其unicodeScalars屬性來訪問值的Unicode標量表示此屬性的類型是類型UnicodeScalarView值的集合UnicodeScalar

每一個UnicodeScalar都有一個value屬性,返回標量的21位值,表示在一個UInt32值內:

../_images/UnicodeScalar_2x.png
  1. for scalar in dogString.unicodeScalars {
  2. print("\(scalar.value) ", terminator: "")
  3. }
  4. print("")
  5. // Prints "68 111 103 8252 128054 "

value前三個屬性UnicodeScalar值(68111103)再次表示字符Dog

第四codeUnit值(8252)再次是十六進制值的十進位等值203C,它表明了Unicode標U+203C字符。DOUBLE EXCLAMATION MARK

value第五和最後的屬性UnicodeScalar128054是十六進制值的十進位等值1F436,它表明了Unicode標U+1F436字符。DOG FACE

做爲查詢其value屬性的替代方法,每一個UnicodeScalar值也可用於構造新String值,例如使用字符串插值:

  1. for scalar in dogString.unicodeScalars {
  2. print("\(scalar) ")
  3. }
  4. // D
  5. // o
  6. // g
  7. // ‼
  8. // 🐶
相關文章
相關標籤/搜索