Lesson 9 - Strings in Swift - Split
In the previous exercise, Solved tasks for Swift lesson 8, we've practiced our knowledge from previous lessons.
In today's Swift tutorial, we're going to explain other String
methods that I have intentionally kept from you because we didn't know that
strings are similar to arrays
On strings we can use many methods and properties which we know from arrays
in a similar fashion. For example: first
, last
,
index()
and others.
When you create an arbitrary variable and write a dot after it, XCode will show us all of the available methods and variables, that we can call on that variable (we'll go deeper into this in the OOP course). Let's try it out:
The same suggestion can also be accessed by pressing Ctrl + Spacebar when the text cursor is on the dot. Of course, this applies to all variables and classes (we'll use it further along the way, as well). The methods are ordered alphabetically and we can list them using the arrow keys. Xcode shows us the description of the methods, what they do, and what parameters do they need.
Let's talk about the following methods and demonstrate them on simple examples:
Additional String methods
insert()
Inserts a substring into the string at a specific position. The parameters are the position in the string and the substring.
var text = "I would banish all of these Internets." text.insert(contentsOf: "n't", at: text.index(text.startIndex, offsetBy: 7)) print(text)
The output:
I wouldn't banish all of these Internets.
remove()
and
removeSubrange()
The remove()
method is very simple, but it can only remove one
character at a given index. Again, the index must be specified as the
String.Index
data type we have already encountered.
removeSubrange()
removes a substring from our string, but again, we
need to pass it String.Index
via the Range
data type
which makes it more complicated.
Range
represents an interval and we specify it using three dots.
We've already met it with loops for i in 1...5
, does that ring any bells? Similarly, we
can create a Range
from String.Index
. Let's show a
couple of examples.
var text = "He who laughs last is the admin."
text.remove(at: text.startIndex)
print(text)
Výstup:
e who laughs last is the admin.
And a removeSubrange()
example:
var text = "He who laughs last is the admin." text.removeSubrange(text.index(text.startIndex, offsetBy: 2)..<text.endIndex) print(text)
The output:
He
Note that in Range
we need to use the <
(less
than) operator, otherwise endIndex
would make us overflow one
position outside of the String
via and the program would crash.
Substring()
We use substring to retrieve part of a String
. Earlier versions
of Swift offered a method of the same name. But it's deprecated and now we use
brackets to get a substring. This is called "slicing", as if we were slicing
strings. Again, let's show some examples and then explain them.
let text = "He who laughs last. He's the admin!" let endIndex = text.index(of: ".")! let substring = String(text[...endIndex]) print(substring)
The output:
He who laughs last.
Let's try another example:
let text = "He who laughs last. He's the admin!" let startIndex = text.index(of: ".")! let substring = String(text[startIndex...]) print(substring)
The output:
. He's the admin!
And the last one:
let text = "He who laughs last. He's the admin!" let startIndex = text.index(text.startIndex, offsetBy: 3) let endIndex = text.index(startIndex, offsetBy: 14) let substring = String(text[startIndex...endIndex]) print(substring)
The output:
laughs last
As you can see, we need to work with the String.Index
types
again so the code has multiple lines. We also used Range
limited
from one side only. This way, you can get the entire substring from a particular
index or till a particular index. In the last example, we used the standard
Range
limited on both sides and we also retrieved the
endIndex
using the startIndex
. All these slicing
operations don't return a String
, but the Substring
type which is best to convert back to a String
right away. It's
recommended by Apple in their documentation and one of the reasons for it is
that Substring
keeps the original String
stored in
memory, although we don't plan to work with it.
compare()
The method allows us to compare two strings alphabetically. We get the result
of the comparison through the rawValue
property. It contains
-1
if the string is before the string given as a parameter,
0
if they are equal and 1
if the string is after one
in the parameter:
print("alpha".compare("bravo").rawValue)
The output:
-1
Now let's look at 2 more, very useful, String
methods.
split()
and joined()
From the previous lesson, we know that parsing strings character by character
can be rather complicated. Even though we made a fairly simple example. Of
course, we'll encounter strings all the time, both in user inputs, e.g. from the
console or from input fields in form applications, and in TXT and XML files.
Very often, we're given one long string
, a line in a file or in the
console, in which there are multiple values separated by separators, e.g.
commas. In this case, we're talking about the CSV format (Comma-Separated
Values). To be sure that we all know what we're talking about, let's look at
some sample strings:
Jessie,Brown,Wall Street 10,New York,130 00 .. ... .-.. .- -. -.. ... --- ..-. - (1,2,3;4,5,6;7,8,9)
- The first string clearly represents a user. We could, for example, store users into a CSV file (one per line).
- The second string is Morse code characters and uses the space character as the separator.
- The third string is a matrix of 3 columns and 3 rows. The column separator is a comma, whereas the row separator is a semicolon.
We can call the split()
method on a String
, which
takes a separator as a Character
. It'll then split the original
string using the separator into an array of substrings and return it. This will
greatly simplify value extraction from strings for our current intents and
purposes.
The joined()
method, on the other hand, merges
an array of substrings using a separator into a single string. The parameter is
the separator. The output of the method is the resulting string. The method can
be also called without a parameter, thus joining strings without separators.
Right then, let's see what we've got up until now. We still don't know how to declare objects, users, or even work with multidimensional arrays, i.e. matrices. Nevertheless, we want to make something cool, so we'll settle with making a Morse code message decoder.
Morse code decoder
We'll start out by preparing the program structure, as always. We need two strings for the messages, one for a message in Morse code, the other one will be empty for now and we'll store the results of our efforts there. Next, we need letter definitions (as we had with vowels). Of course, we'll also need the Morse code versions of the letter definitions. We'll use arrays for both definitions this time since Morse letters consist of multiple text characters.
The structure of our program should now look something like this:
// the string which we want to decode let s = ".. -.-. - ... --- -.-. .. .- .-.." print("The original message: $s") // the string with a decoded message var message = "" // array definitions let alphabetChars = ["a", "b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"] let morseChars = [".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."]
Why we defined the alphabet as an array too? It'll save us a lot of effort
when searching for a character by the Morse character representation. Otherwise,
we'd have to deal with conversion of an Array.Index
to a
String.Index
and the code would be much longer.
We could also add other Morse characters such as numbers and punctuation
marks, but we won't worry about them for now. We'll split the String
s
with the split()
method into an array of substrings
containing the Morse characters. We'll split it by the space character. Then
we'll iterate over the array using a for in
loop:
// splitting the string into Morse characters let characters = s.split(separator: " ") // iterating over Morse characters for morseChar in characters { }
Ideally, we should somehow deal with cases when the user enters e.g. multiple
spaces between characters (users often do things of the sort). In this case,
split()
creates one more empty substring in the array. We should
then detect it in the loop and ignore it, but we won't deal with that in this
lesson.
In the loop, we'll attempt to find the current Morse character in the
morseChars
array. We'll be interested in its index
because when we look at that same index in the alphabetChars
array,
there will be the corresponding letter. This is mainly because both the arrays
contain the same characters which are ordered alphabetically. Let's place the
following code into the loop's body:
let index = morseChars.index(of: String(morseChar)) // opening the Optional, character was found if let index = index { message += alphabetChars[index] }
We try to find the Morse code character index. If we succeed, we find the
corresponding letter in the alphabet and we add it to the message. The
+=
operator works the same as
message = message + alphabetChar
.
Now, we'll print the message:
// the string which we want to decode let s = ".. -.-. - ... --- -.-. .. .- .-.." print("The original message: $s") // the string with a decoded message var message = "" // array definitions let alphabetChars = ["a", "b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"] let morseChars = [".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."] // splitting the string into Morse characters let characters = s.split(separator: " ") // iterating over Morse characters for morseChar in characters { let index = morseChars.index(of: String(morseChar)) // opening the Optional, character was found if let index = index { message += alphabetChars[index] } } println("The decoded message: $message")
The output:
The original message: .. -.-. - ... --- -.-. .. .- .-.. The decoded message: ictsocial
Done! If you want to train some more, you can create a program which would
encode a string to the Morse code. The code would be very similar. We'll use the
split()
and joined()
methods several more times
throughout our Swift courses.
Special characters and escaping
Strings can contain special characters which are prefixed with backslash
\
. Mainly, the \n
character, which causes a line break
anywhere in the text, and \t
, which is the tab character.
Let's test them out:
print("First line\nSecond line")
The "\" character indicates a special character sequence in a string and can
be used also e.g. to write Unicode characters as \u{xxxx}
where
xxxx is the character code.
The problem might be when we want to write \
itself, in this
case we've to escape it by writing one more \
:
print("This is a backslash: \\")
We can escape a quotation mark in the same way, so Swift wouldn't misinterpret it as the end of the string:
print("This is a quotation mark: \"")
Inputs from the console and input fields in form applications are, of course,
escaped automatically, so the user wouldn't be able to enter \n
,
\t
, etc.. Programmers are allowed to write these characters in the
code, so we have to keep escaping in mind.
Today we basically finished the on-line course on the Swift basic constructs.
In the following exercise, Solved tasks for Swift lesson 9, we're gonna practice our knowledge from previous lessons.
Download
By downloading the following file, you agree to the license termsDownloaded 504x (32.64 kB)