What this lesson covers
A Swift String is a sequence of Character values. This lesson shows how to create strings, join them, take parts of them, change them and loop over them. The exercise at the end builds "TypeScript" out of "Java" using most of these tools.
Creating, measuring and joining
Strings are written in double quotes. count gives the number of characters, last gives the final character as an optional (it is nil for an empty string), and + joins two strings:
let str = "Hello"
print(str.count, str.last!, str[str.startIndex])
let name = "John"
var greet = "Welcome"
greet += " to the course, "
greet += name
print(greet)
5 o H
Welcome to the course, John
The ! after last unwraps the optional and stops the program if it is nil. Use it only when the string cannot be empty. To build a long result from many pieces, collect them in an array and call joined() once.
Indexing and slicing
A string cannot be subscripted with an integer. The compiler rejects str[0]. You ask the string for an index with index(_:offsetBy:) and subscript with that:
let text = "JavaScript"
let start = text.index(text.startIndex, offsetBy: 2)
let end = text.index(text.startIndex, offsetBy: 6)
let substr = String(text[start..<end])
print(substr)
print(String(text[text.index(text.startIndex, offsetBy: 4)...]))
vaSc
Script
The range start..<end stops before end, and start... runs to the end of the string. Subscripting with a range returns a Substring, a view into the original string, so wrap it in String(...) when you want a separate string. An offset beyond the end of the string stops the program with an "index out of bounds" error.
For the common cases there are shortcuts. dropFirst(4) skips the first four characters, prefix(2) keeps the first two and suffix(3) keeps the last three. They also return substrings.
Strings are values
A string held in a let cannot change at all. A string held in a var can be assigned a new value or appended to, but you cannot replace one character in place. To get "Job" from "Bob", build a new string:
var myStr = "Bob"
myStr = "J" + String(myStr[myStr.index(after: myStr.startIndex)...])
print(myStr)
Job
Building a new string copies all the characters, so it costs O(n). If you must change many characters, convert once to an array of characters, edit the array, and convert back:
var word = "Andy"
var chars = Array(word)
chars[0] = "a"
chars[2] = "D"
word = String(chars)
print(word)
anDy
An array element can be changed in O(1), and the two conversions cost O(n) each. Note that the new elements are written in double quotes too: Swift reads "a" as a Character when the array holds characters.
Looping over a string
A for-in loop visits each character in order, in O(n) time:
for ch in "Andy" {
print(ch)
}
A
n
d
y
The exercise, step by step
- Create
lang. Declare it withvarand the value"Java", because the next step changes it. - Append.
lang += "script"makes it"Javascript". - Take the tail.
lang.dropFirst(4)skips"Java"and leaves"script"as aSubstring. Wrapping it inString(...)gives the constantsubstring. - Join.
"Type" + substringgives"Typescript"in avarcallednewLang. - Convert to characters.
Array(newLang)gives a[Character]namedcharacters, which can be indexed with integers. - Capitalize. The lowercase s is the fifth character, index 4, so
characters[4] = "S". - Convert back.
String(characters)is assigned tonewLang, which now holds"TypeScript".
var lang = "Java"
lang += "script"
let substring = String(lang.dropFirst(4))
var newLang = "Type" + substring
var characters = Array(newLang)
characters[4] = "S"
newLang = String(characters)
Printing the variables afterwards shows Javascript, script and TypeScript.
Common mistakes
- Using
str[0]. It does not compile. Use an index, orArray(str). - Joining a
Characterto aStringwith+. WriteString(ch)first. - Forgetting
String(...)around a slice. The result is aSubstring, which cannot be assigned to aStringvariable. - Off-by-one in offsets. Offsets start at 0, and the end of a
..<range is excluded.
Key takeaways
- Strings are collections of
Charactervalues;countcounts characters. - Use
String.IndexorArray(str)for positions, andString(...)to turn slices and arrays back into strings. - Strings are values: changing one means building a new one.
