Swift Language
Ciągi i znaki
Szukaj…
Składnia
- String.characters // Zwraca tablicę znaków w ciągu
- String.characters.count // Zwraca liczbę znaków
- String.utf8 // A String.UTF8View, zwraca punkty znakowe UTF-8 w ciągu
- String.utf16 // A String.UTF16View, zwraca punkty znakowe UTF-16 w ciągu
- String.unicodeScalars // A String.UnicodeScalarView, zwraca punkty znakowe UTF-32 w ciągu
- String.isEmpty // Zwraca wartość true, jeśli ciąg nie zawiera żadnego tekstu
- String.hasPrefix (String) // Zwraca wartość true, jeśli ciąg jest poprzedzony argumentem
- String.hasSuffix (String) // Zwraca wartość true, jeśli ciąg jest uzupełniony argumentem
- String.startIndex // Zwraca indeks, który odpowiada pierwszemu znakowi w ciągu
- String.endIndex // Zwraca indeks, który odpowiada miejscu po ostatnim znaku w ciągu
- String.components (ortedBy: String) // Zwraca tablicę zawierającą podciągi rozdzielone danym ciągiem separatora
- String.append (Character) // Dodaje znak (podany jako argument) do ciągu
Uwagi
String
in Swift to zbiór znaków, a przez to zbiór skalarów Unicode. Ponieważ ciągi Swift są oparte na Unicode, mogą to być dowolne wartości skalarne Unicode, w tym języki inne niż angielski i emoji.
Ponieważ dwa skalary mogą łączyć się w jeden znak, liczba skalarów w ciągu nie zawsze musi być taka sama jak liczba znaków.
Aby uzyskać więcej informacji o ciągach, zobacz Swift Programming Language i odwołanie do struktury ciągów .
Aby uzyskać szczegółowe informacje na temat implementacji, zobacz „Swift String Design”
Literały ciągów znaków
Literały łańcuchowe w Swift są oddzielone podwójnymi cudzysłowami ( "
):
let greeting = "Hello!" // greeting's type is String
Znaki można inicjalizować z literałów łańcuchowych, o ile literały zawierają tylko jeden klaster grafemowy:
let chr: Character = "H" // valid
let chr2: Character = "😊" // valid
let chr3: Character = "abc" // invalid - multiple grapheme clusters
Interpolacja ciągów
Interpolacja ciągów znaków umożliwia wstrzyknięcie wyrażenia bezpośrednio w literał łańcucha. Można tego dokonać przy użyciu wszystkich typów wartości, w tym ciągów, liczb całkowitych, liczb zmiennoprzecinkowych i innych.
Składnia to ukośnik odwrotny, po którym następuje nawias owinięty wartością: \(value)
. W nawiasach może pojawić się dowolne prawidłowe wyrażenie, w tym wywołania funkcji.
let number = 5
let interpolatedNumber = "\(number)" // string is "5"
let fortyTwo = "\(6 * 7)" // string is "42"
let example = "This post has \(number) view\(number == 1 ? "" : "s")"
// It will output "This post has 5 views" for the above example.
// If the variable number had the value 1, it would output "This post has 1 view" instead.
W przypadku typów niestandardowych domyślne zachowanie interpolacji ciągów jest takie, że "\(myobj)"
jest równoważne String(myobj)
, takiej samej reprezentacji, jak w przypadku print(myobj)
. Możesz dostosować to zachowanie, implementując protokół CustomStringConvertible
dla swojego typu.
W przypadku Swift 3, zgodnie z SE-0089 , String.init<T>(_:)
na String.init<T>(describing:)
.
Interpolacja ciągów "\(myobj)"
będzie preferować nowy String.init<T: LosslessStringConvertible>(_:)
, ale wróci do init<T>(describing:)
jeśli wartość nie jest LosslessStringConvertible
.
Znaki specjalne
Niektóre znaki wymagają specjalnej sekwencji ucieczki, aby użyć ich w literałach łańcuchowych:
Postać | Znaczenie |
---|---|
\0 | znak zerowy |
\\ | zwykły ukośnik odwrotny, \ |
\t | znak tabulacji |
\v | pionowa zakładka |
\r | powrót karetki |
\n | nowy wiersz („nowa linia”) |
\" | podwójny cytat " |
\' | pojedynczy cytat ' |
\u{n} | punkt kodowy Unicode n (w systemie szesnastkowym) |
Przykład:
let message = "Then he said, \"I \u{1F496} you!\""
print(message) // Then he said, "I 💖 you!"
Połącz ciągi znaków
Połącz łańcuchy z operatorem +
, aby utworzyć nowy łańcuch:
let name = "John"
let surname = "Appleseed"
let fullName = name + " " + surname // fullName is "John Appleseed"
Dołącz do zmiennej ciągu za pomocą operatora +=
operator przypisania lub za pomocą metody:
let str2 = "there"
var instruction = "look over"
instruction += " " + str2 // instruction is now "look over there"
var instruction = "look over"
instruction.append(" " + str2) // instruction is now "look over there"
Dodaj pojedynczy znak do zmiennego ciągu:
var greeting: String = "Hello"
let exclamationMark: Character = "!"
greeting.append(exclamationMark)
// produces a modified String (greeting) = "Hello!"
Dołącz wiele znaków do zmiennego ciągu
var alphabet:String = "my ABCs: "
alphabet.append(contentsOf: (0x61...0x7A).map(UnicodeScalar.init)
.map(Character.init) )
// produces a modified string (alphabet) = "my ABCs: abcdefghijklmnopqrstuvwxyz"
appendContentsOf(_:)
został przemianowany na append(_:)
.
Połącz sekwencję ciągów, aby utworzyć nowy ciąg za pomocą joinWithSeparator(_:)
:
let words = ["apple", "orange", "banana"]
let str = words.joinWithSeparator(" & ")
print(str) // "apple & orange & banana"
joinWithSeparator(_:)
został przemianowany na joinWithSeparator(_:)
joined(separator:)
.
separator
jest domyślnie pustym ciągiem, więc ["a", "b", "c"].joined() == "abc"
.
Sprawdź i porównaj ciągi
Sprawdź, czy ciąg jest pusty:
if str.isEmpty {
// do something if the string is empty
}
// If the string is empty, replace it with a fallback:
let result = str.isEmpty ? "fallback string" : str
Sprawdź, czy dwa łańcuchy są równe (w znaczeniu równoważności kanonicznej Unicode ):
"abc" == "def" // false
"abc" == "ABC" // false
"abc" == "abc" // true
// "LATIN SMALL LETTER A WITH ACUTE" == "LATIN SMALL LETTER A" + "COMBINING ACUTE ACCENT"
"\u{e1}" == "a\u{301}" // true
Sprawdź, czy ciąg zaczyna się / kończy innym ciągiem:
"fortitude".hasPrefix("fort") // true
"Swift Language".hasSuffix("age") // true
Kodowanie i rozkład łańcuchów
Swift String składa się z punktów kodu Unicode . Można go rozłożyć i zakodować na kilka różnych sposobów.
let str = "ที่👌①!"
Rozkładanie ciągów
characters
są rozszerzonymi klastrami grafem Unicode:
Array(str.characters) // ["ที่", "👌", "①", "!"]
unicodeScalars
to punkty kodowe Unicode, które tworzą ciąg znaków (zauważ, że ที่
jest jednym klastrem ที่
, ale 3 punkty kodowe - 3607, 3637, 3656 - więc długość wynikowej tablicy nie jest taka sama jak w przypadku characters
):
str.unicodeScalars.map{ $0.value } // [3607, 3637, 3656, 128076, 9312, 33]
Możesz kodować i dekomponować ciągi jako UTF-8 (sekwencja UInt8
s) lub UTF-16 (sekwencja UInt16
s):
Array(str.utf8) // [224, 184, 151, 224, 184, 181, 224, 185, 136, 240, 159, 145, 140, 226, 145, 160, 33]
Array(str.utf16) // [3607, 3637, 3656, 55357, 56396, 9312, 33]
Długość i iteracja łańcucha
characters
, unicodeScalars
, utf8
i utf16
są kolekcjami , więc możesz uzyskać ich count
i iterować nad nimi:
// NOTE: These operations are NOT necessarily fast/cheap!
str.characters.count // 4
str.unicodeScalars.count // 6
str.utf8.count // 17
str.utf16.count // 7
for c in str.characters { // ...
for u in str.unicodeScalars { // ...
for byte in str.utf8 { // ...
for byte in str.utf16 { // ...
Unicode
Ustawianie wartości
Korzystanie bezpośrednio z Unicode
var str: String = "I want to visit 北京, Москва, मुंबई, القاهرة, and 서울시. 😊"
var character: Character = "🌍"
Używanie wartości szesnastkowych
var str: String = "\u{61}\u{5927}\u{1F34E}\u{3C0}" // a大🍎π
var character: Character = "\u{65}\u{301}" // é = "e" + accent mark
Zauważ, że Szybki Character
może składać się z wielu punktów kodu Unicode, ale wydaje się być pojedynczym znakiem. To się nazywa klaster Extended Grapheme.
Konwersje
String -> Hex
// Accesses views of different Unicode encodings of `str`
str.utf8
str.utf16
str.unicodeScalars // UTF-32
Hex -> String
let value0: UInt8 = 0x61
let value1: UInt16 = 0x5927
let value2: UInt32 = 0x1F34E
let string0 = String(UnicodeScalar(value0)) // a
let string1 = String(UnicodeScalar(value1)) // 大
let string2 = String(UnicodeScalar(value2)) // 🍎
// convert hex array to String
let myHexArray = [0x43, 0x61, 0x74, 0x203C, 0x1F431] // an Int array
var myString = ""
for hexValue in myHexArray {
myString.append(UnicodeScalar(hexValue))
}
print(myString) // Cat‼🐱
Zauważ, że w przypadku UTF-8 i UTF-16 konwersja nie zawsze jest taka łatwa, ponieważ takich rzeczy jak emoji nie można zakodować za pomocą pojedynczej wartości UTF-16. Wymaga pary zastępczej.
Cofanie ciągów znaków
let aString = "This is a test string."
// first, reverse the String's characters
let reversedCharacters = aString.characters.reverse()
// then convert back to a String with the String() initializer
let reversedString = String(reversedCharacters)
print(reversedString) // ".gnirts tset a si sihT"
let reversedCharacters = aString.characters.reversed()
let reversedString = String(reversedCharacters)
Wielkie i małe litery
Aby wszystkie znaki w ciągach były pisane wielkimi lub małymi literami:
let text = "AaBbCc"
let uppercase = text.uppercaseString // "AABBCC"
let lowercase = text.lowercaseString // "aabbcc"
let text = "AaBbCc"
let uppercase = text.uppercased() // "AABBCC"
let lowercase = text.lowercased() // "aabbcc"
Sprawdź, czy ciąg zawiera znaki ze zdefiniowanego zestawu
Listy
let letters = CharacterSet.letters
let phrase = "Test case"
let range = phrase.rangeOfCharacter(from: letters)
// range will be nil if no letters is found
if let test = range {
print("letters found")
}
else {
print("letters not found")
}
let letters = NSCharacterSet.letterCharacterSet()
let phrase = "Test case"
let range = phrase.rangeOfCharacterFromSet(letters)
// range will be nil if no letters is found
if let test = range {
print("letters found")
}
else {
print("letters not found")
}
Nowa struktura CharacterSet
która jest również połączona z klasą NSCharacterSet
Objective-C, definiuje kilka predefiniowanych zestawów jako:
-
decimalDigits
-
capitalizedLetters
-
alphanumerics
-
controlCharacters
-
illegalCharacters
- i więcej można znaleźć w odnośniku NSCharacterSet .
Możesz także zdefiniować własny zestaw znaków:
let phrase = "Test case"
let charset = CharacterSet(charactersIn: "t")
if let _ = phrase.rangeOfCharacter(from: charset, options: .caseInsensitive) {
print("yes")
}
else {
print("no")
}
let charset = NSCharacterSet(charactersInString: "t")
if let _ = phrase.rangeOfCharacterFromSet(charset, options: .CaseInsensitiveSearch, range: nil) {
print("yes")
}
else {
print("no")
}
Możesz także podać zakres:
let phrase = "Test case"
let charset = CharacterSet(charactersIn: "t")
if let _ = phrase.rangeOfCharacter(from: charset, options: .caseInsensitive, range: phrase.startIndex..<phrase.endIndex)) {
print("yes")
}
else {
print("no")
}
Policz wystąpienia postaci w ciągu
Biorąc pod uwagę String
i Character
let text = "Hello World"
let char: Character = "o"
Możemy policzyć ile razy Character
pojawia się w String
za pomocą
let sensitiveCount = text.characters.filter { $0 == char }.count // case-sensitive
let insensitiveCount = text.lowercaseString.characters.filter { $0 == Character(String(char).lowercaseString) } // case-insensitive
Usuń znaki z ciągu niezdefiniowanego w zestawie
func removeCharactersNotInSetFromText(text: String, set: Set<Character>) -> String {
return String(text.characters.filter { set.contains( $0) })
}
let text = "Swift 3.0 Come Out"
var chars = Set([Character]("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters))
let newText = removeCharactersNotInSetFromText(text, set: chars) // "SwiftComeOut"
func removeCharactersNotInSetFromText(text: String, set: Set<Character>) -> String {
return String(text.characters.filter { set.contains( $0) })
}
let text = "Swift 3.0 Come Out"
var chars = Set([Character]("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters))
let newText = removeCharactersNotInSetFromText(text: text, set: chars)
Formatowanie ciągów
Wiodące Zero
let number: Int = 7
let str1 = String(format: "%03d", number) // 007
let str2 = String(format: "%05d", number) // 00007
Liczby po przecinku
let number: Float = 3.14159
let str1 = String(format: "%.2f", number) // 3.14
let str2 = String(format: "%.4f", number) // 3.1416 (rounded)
Dziesiętny do szesnastkowego
let number: Int = 13627
let str1 = String(format: "%2X", number) // 353B
let str2 = String(format: "%2x", number) // 353b (notice the lowercase b)
Alternatywnie można użyć specjalistycznego inicjatora, który robi to samo:
let number: Int = 13627
let str1 = String(number, radix: 16, uppercase: true) //353B
let str2 = String(number, radix: 16) // 353b
Dziesiętny do liczby z dowolną podstawą
let number: Int = 13627
let str1 = String(number, radix: 36) // aij
Radix jest Int
w [2, 36]
.
Konwertowanie ciągu Swift na typ liczbowy
Int("123") // Returns 123 of Int type
Int("abcd") // Returns nil
Int("10") // Returns 10 of Int type
Int("10", radix: 2) // Returns 2 of Int type
Double("1.5") // Returns 1.5 of Double type
Double("abcd") // Returns nil
Pamiętaj, że wykonanie tej czynności zwraca wartość Optional
, którą należy odpowiednio rozpakować przed użyciem.
Iteracja łańcucha
let string = "My fantastic string"
var index = string.startIndex
while index != string.endIndex {
print(string[index])
index = index.successor()
}
Uwaga: endIndex
występuje po końcu łańcucha (tzn. string[string.endIndex]
jest błędem, ale string[string.startIndex]
jest w porządku). Ponadto w pustym ciągu ( ""
) string.startIndex == string.endIndex
ma wartość true
. Pamiętaj, aby sprawdzić puste ciągi, ponieważ nie można wywołać startIndex.successor()
na pustym ciągu.
W Swift 3 indeksy łańcuchowe nie mają już successor()
, predecessor()
, advancedBy(_:)
, advancedBy(_:limit:)
lub distanceTo(_:)
.
Zamiast tego operacje te są przenoszone do kolekcji, która jest teraz odpowiedzialna za zwiększanie i zmniejszanie jej wskaźników.
Dostępne metody to .index(after:)
, .index(before:)
i .index(_:, offsetBy:)
.
let string = "My fantastic string"
var currentIndex = string.startIndex
while currentIndex != string.endIndex {
print(string[currentIndex])
currentIndex = string.index(after: currentIndex)
}
Uwaga: używamy currentIndex
jako nazwy zmiennej, aby uniknąć pomyłek z metodą .index
.
I na przykład, jeśli chcesz pójść w drugą stronę:
var index:String.Index? = string.endIndex.predecessor()
while index != nil {
print(string[index!])
if index != string.startIndex {
index = index.predecessor()
}
else {
index = nil
}
}
(Lub możesz po prostu najpierw odwrócić ciąg, ale jeśli nie musisz przechodzić przez cały ciąg, prawdopodobnie wolisz taką metodę)
var currentIndex: String.Index? = string.index(before: string.endIndex)
while currentIndex != nil {
print(string[currentIndex!])
if currentIndex != string.startIndex {
currentIndex = string.index(before: currentIndex!)
}
else {
currentIndex = nil
}
}
Uwaga: Index
jest typem obiektu, a nie Int
. Nie możesz uzyskać dostępu do znaku ciągu w następujący sposób:
let string = "My string"
string[2] // can't do this
string.characters[2] // and also can't do this
Ale możesz uzyskać określony indeks w następujący sposób:
index = string.startIndex.advanceBy(2)
currentIndex = string.index(string.startIndex, offsetBy: 2)
I może cofać się w ten sposób:
index = string.endIndex.advancedBy(-2)
currentIndex = string.index(string.endIndex, offsetBy: -2)
Jeśli możesz przekroczyć granice ciągu lub chcesz określić limit, którego możesz użyć:
index = string.startIndex.advanceBy(20, limit: string.endIndex)
currentIndex = string.index(string.startIndex, offsetBy: 20, limitedBy: string.endIndex)
Alternatywnie można po prostu iterować znaki w ciągu, ale może to być mniej przydatne w zależności od kontekstu:
for c in string.characters {
print(c)
}
Usuń wiodące i końcowe WhiteSpace i NewLine
let someString = " Swift Language \n"
let trimmedString = someString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
// "Swift Language"
Metoda stringByTrimmingCharactersInSet
zwraca nowy ciąg utworzony przez usunięcie z obu końców znaków String zawartych w danym zestawie znaków.
Możemy również usunąć tylko białe znaki lub nową linię.
Usuwanie tylko białych znaków:
let trimmedWhiteSpace = someString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
// "Swift Language \n"
Usuwanie tylko nowej linii:
let trimmedNewLine = someString.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
// " Swift Language "
let someString = " Swift Language \n"
let trimmedString = someString.trimmingCharacters(in: .whitespacesAndNewlines)
// "Swift Language"
let trimmedWhiteSpace = someString.trimmingCharacters(in: .whitespaces)
// "Swift Language \n"
let trimmedNewLine = someString.trimmingCharacters(in: .newlines)
// " Swift Language "
Uwaga: wszystkie te metody należą do Foundation
. Użyj import Foundation
jeśli Foundation nie jest już importowana przez inne biblioteki, takie jak Cocoa lub UIKit.
Konwertuj ciąg na dane iz danych / NSData
Aby przekonwertować ciąg na dane i dane / NSData, musimy zakodować ten ciąg za pomocą specjalnego kodowania. Najbardziej znanym jest UTF-8
który jest 8-bitową reprezentacją znaków Unicode, odpowiedni do transmisji lub przechowywania przez systemy oparte na ASCII. Oto lista wszystkich dostępnych String Encodings
String
do Data
/ NSData
let data = string.data(using: .utf8)
let data = string.dataUsingEncoding(NSUTF8StringEncoding)
Data
/ NSData
na String
let string = String(data: data, encoding: .utf8)
let string = String(data: data, encoding: NSUTF8StringEncoding)
Podział łańcucha na tablicę
W Swift możesz łatwo oddzielić ciąg znaków do tablicy, krojąc go na określony znak:
let startDate = "23:51"
let startDateAsArray = startDate.components(separatedBy: ":") // ["23", "51"]`
let startDate = "23:51"
let startArray = startDate.componentsSeparatedByString(":") // ["23", "51"]`
Lub gdy separator nie jest obecny:
let myText = "MyText"
let myTextArray = myText.components(separatedBy: " ") // myTextArray is ["MyText"]
let myText = "MyText"
let myTextArray = myText.componentsSeparatedByString(" ") // myTextArray is ["MyText"]