Zastosowano wszystkie poniższe przykłady
var str = "Hello, playground"
Szybki 4
Ciągi zostały dość gruntownie zmienione w Swift 4. Kiedy teraz otrzymujesz podciąg z String, dostajesz z Substring
powrotem typ zamiast a String
. Dlaczego to? Ciągi są typami wartości w Swift. Oznacza to, że jeśli użyjesz jednego ciągu, aby utworzyć nowy, należy go skopiować. Jest to dobre dla stabilności (nikt inny nie zmieni tego bez twojej wiedzy), ale złe dla wydajności.
Z drugiej strony podłańcuch jest odniesieniem do oryginalnego ciągu, z którego pochodzi. Oto obraz z dokumentacji ilustrujący to.
Kopiowanie nie jest potrzebne, więc jest znacznie wydajniejsze w użyciu. Wyobraź sobie jednak, że masz dziesięcioznakowy podłańcuch z milionowego ciągu znaków. Ponieważ podłańcuch odwołuje się do ciągu, system musiałby trzymać się całego ciągu tak długo, jak długo znajduje się on w pobliżu. Dlatego za każdym razem, gdy skończysz manipulować swoim podciągiem, przekonwertuj go na ciąg.
let myString = String(mySubstring)
Spowoduje to skopiowanie tylko podciągu, a pamięć zawierająca stary ciąg może zostać odzyskana . Podciągi (jako typ) mają być krótkotrwałe.
Kolejną dużą poprawą w Swift 4 jest to, że ciągi są kolekcjami (ponownie). Oznacza to, że cokolwiek możesz zrobić z kolekcją, możesz zrobić z łańcuchem (użyj indeksów dolnych, iteruj po znakach, filtruj itp.).
Poniższe przykłady pokazują, jak uzyskać podciąg w Swift.
Pobieranie podciągów
Można uzyskać podciąg z ciągu znaków za pomocą indeksów lub szereg innych metod (na przykład prefix
, suffix
, split
). Nadal jednak musisz używać indeksu dla zakresu, String.Index
a nie Int
indeksu. (Zobacz moją drugą odpowiedź, jeśli potrzebujesz pomocy.)
Początek łańcucha
Możesz użyć indeksu dolnego (zwróć uwagę na jednostronny zakres Swift 4):
let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello
lub prefix
:
let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello
lub nawet łatwiej:
let mySubstring = str.prefix(5) // Hello
Koniec łańcucha
Korzystanie z indeksów dolnych:
let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground
lub suffix
:
let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground
lub nawet łatwiej:
let mySubstring = str.suffix(10) // playground
Zauważ, że podczas używania suffix(from: index)
musiałem odliczać od końca, używając -10
. Nie jest to konieczne przy zwykłym użyciu suffix(x)
, które po prostu pobiera ostatnie x
znaki ciągu.
Zakres w ciągu
Ponownie używamy tutaj indeksów dolnych.
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
let mySubstring = str[range] // play
Konwertowanie Substring
naString
Nie zapominaj, że kiedy będziesz gotowy do zapisania swojego podciągu, powinieneś przekonwertować go na String
tak, aby pamięć starego łańcucha mogła zostać wyczyszczona.
let myString = String(mySubstring)
Używasz Int
rozszerzenia indeksu?
Waham się przed użyciem Int
rozszerzenia indeksu opartego na indeksie po przeczytaniu artykułu Strings in Swift 3 autorstwa Airspeed Velocity i Ole Begemann. Chociaż w Swift 4 Strings są kolekcjami, zespół Swift celowo nie używał Int
indeksów. Nadal jest String.Index
. Ma to związek z tym, że znaki Swift składają się z różnej liczby punktów kodowych Unicode. Rzeczywisty indeks musi być jednoznacznie obliczony dla każdego łańcucha.
Muszę powiedzieć, że mam nadzieję, że zespół Swift znajdzie sposób na abstrahowanie String.Index
w przyszłości. Ale dopóki nie zdecyduję się użyć ich interfejsu API. Pomaga mi pamiętać, że manipulacje ciągami znaków to nie tylko proste Int
wyszukiwanie indeksów.