Saturday, May 5, 2018

Swift 4 Introduction Series 1.10 - All About Strings

In Swift, String is the data type that handles text. This is the most frequently used data type. Swift also includes a data type known as Character, that holds a single character.

String Literals

String literals are basically the raw text that Swift could accept. Swift could accept all kinds of  text in unicode except backslash(\), double quotation(") and triple double quotation (""").


Double quotation is used to enclose the text and it is the marker that marks the beginning and the end of text. Triple double quotation is used to enclose the text for multiline text.


Example:

"This is a text"

"!@#$%^&*()_+=-:';><?,./|{}[]"


Multiline String Literals

In Swift 4, String supports multiline literals. To create multiline literals, we enclose the entire text using triple double quotation. The beginning of multiline string must start in a new line after the opening triple double quotation and the string must end a line before the closing triple quotation.


Syntax:


"""
Start of multiline string
End of multiline string
"""


Example:

let story = """
Title
We can include multi line text here.

Next paragraph

End
"""

print(story)

Screen Shot 2017-11-03 at 23.22.49.png















Notice that the multiline text start from the line after opening triple double quotation and ends before the closing triple double quotation. Please also note that any line spacing or line break is included in the string.


The following single line string and multi line string produce the same result


Example:

let single = "This is single line."
let multi = """
This is same as single line.
"""

print(single)
print(multi)

Screen Shot 2017-11-03 at 23.29.28.png











As we have mentioned before, any line break or line spacing is included in the multiline string. However, let's say that we have to break a long sentence into multiline for better readability, but it should not be broken in the multiline text. Then we use the escape sequence (\) as shown in the example below.


In the following example, if we need to break the line in the code but we do not want it to be broken in the string, we insert the escape sequence (\) to break the line in the code. The actual string is not broken


Example:

let storyboard = """
Title of Story
The man said "Hello, how do \
you do?"

End of Story
"""
print(storyboard)

Screen Shot 2017-11-03 at 23.36.31.png

To include line feed before and after multiline text, we need to add an empty line  manually.

Example:

let singleLine = "This is a demo"
print(singleLine)

let story2 = """

Title of Story 2
End of Story 2

"""

print(story2)

// If we do not add space, there will be no line spacing between singleLine and story2

Screen Shot 2017-11-03 at 23.43.53.png

For multiline text, the system will recognize indentation or space by following the indentation of the closing triple double quotation.

Example:

let story3 = """
         Title of Story 3

                   Start of paragraph

         End of Story 3
         """

print(story3)

Screen Shot 2017-11-03 at 23.49.11.png

In the example above, the system follow the closing triple double quotation. Please take note of the position of closing triple double quotation in line 7. Since the closing triple double quotation has the same indentation as the last line "End of Story 3". The system will not indent the last line and the first line since these lines has the same indentation as the closing triple double quotation.


For better illustration, please check the text below:


let text1 = """



Title of Story 3



Start of paragraph

End of Story 3


"""



Using the closing triple double quotation as guide, the system will ignore space or indentation before closing triple double quotation denoted as orange in the diagram above. The system will include space starting from the closing triple double quotation. Hence the space in green is included by the system.


If the closing triple double quotation starts indentation before the beginning of text, then the system will include all the indentation or space as shown below.


Example:

let story3 = """
         Title of Story 3

                   Start of paragraph

         End of Story 3
"""

print(story3)

Screen Shot 2017-11-03 at 23.51.50.png

In the example above, please take note of the position of closing triple double quotation in line 7. In this case, the system will indent or include space from the closing triple double quote to the text.

What happen if the closing triple double quotation indent after the text. In this case, it will produce error as shown below.

Screen Shot 2017-11-03 at 23.53.29.png

Unicode String

Swift can accept any character in the unicode. Unicode is an international standard for encoding text for different languages. Swift are fully unicode complaint.

Example:

"2010年7月,苹果开发者工具部门总监克里斯·拉特納开始着手 Swift 编程语言的設計工作,以一年時間,完成基本架構後,他領導了一個設計團隊大力參與其中。"

"The Swift Programming Language est un manuel de 500 pages disponible gratuitement sur iBookStore permettant de décrire les fonctionnalités du langage."

"その後アップル社内での4年間の開発期間を経て、2014年のWWDCにおいて一般に発表され、同時にアップルに開発者登録している開発者に対してベータ版の提供が開始された。"

"기존의 애플 운영체제용 언어인 오브젝티브-C와 함께 공존할 목적으로 만들어졌다."

"постала прва јавно доступна апликација написана у Свифту."



We can even include drawing box and symbol in the unicode.

Example:

"⊤⊛⊒⊍⊩"



In Swift the strings are formed by Unicode scalar. A unicode scalar is a 21-bit unicode for a character or icon. If we know the unicode number we can use the unicode number to write a Unicode scalar using the following syntax:

"\u{<unicode_number>}"

Please note that unicode range from U+0000 to U+D7FF inclusive, or U+E000 to U+10FFF inclusive. Please note that Unicode scalar do not include U+D800 to U+DFFF. Please also note that not all Unicode scalars are assigned to a character.

Example:

"\u{2EE5}"
"\u{2F25}\u{2F26}"



Example 2:

"\u{2665}"

"\u{20AC}"

"\u{21A4}"

"\u{222D}"



Extended Grapheme Cluster

An extended grapheme cluster is a sequence of unicode to form a character. In a lot of foreign languages, words are formed by a combination of characters or stroke.

Example:

let tibetan1 = "\u{0F40}"
let tibetan2 = "\u{0F7D}"

let tibetan3 = "\u{0F40}\u{0F7D}"



Example 2:

"\u{65}"

"\u{301}"

"\u{65}\u{301}"

"\u{E9}"



Note: the example above shows that a combination of unicode 65 and 301 is equivalent to the character in unicode E9. More similar example below:

Example 3:

"\u{110B}"

"\u{1175}"

"\u{110B}\u{1175}"

"\u{C774}"



Example 4:

"\u{1112}"
"\u{1161}"
"\u{11AB}"

"\u{1112}\u{1161}\u{11AB}"

"\u{D55C}"



When we form a character using different stroke as shown above, it will still consider as 1 character in a string.

Example:

let a1 = "\u{1112}"
let a2 = "\u{1161}"
let a3 = "\u{11AB}"

a1.count
a2.count
a3.count

let a4 = "\u{1112}\u{1161}\u{11AB}"
a4.count

let a5 = "\u{D55C}"
a5.count



Extended grapheme clusters allow us to enclose a character with a circle using unicode 20DD.

Example:

let copyRight = "\u{63}\u{20DD}"
copyRight.count



Please note that since extended grapheme clusters can contain multiple character for a single character formation. When we use the count features, the system will need to go through each character one by one in order to accurately calculate number of character in a string. The longer the string, it will take longer time for the system to count the number of character.

Escape Sequence

Since we need to enclose string with double or triple double quotation, we cannot use double or triple double quotation in a string. To mitigate this problem we create an escape sequence represented by backslash(\). Therefore, we cannot use double quotation ("), triple double quotation (""") and backslash (\) in a string.

To use these 3 symbol, we need to use backslash as the escape sequence. To use double quotation in a string we need to enter \" instead of ", similarly to use backslash in the string we need to enter \\ instead of \. To include triple double quotation, we can use \""" or \"\"\". We do not need escape sequence for double quotation in multiline text.

Example:

let sampleText1 = "She said \"The dateline is unreasonable.\" and I agreed."

print(sampleText1)


let sampleText2 = "To print double quotation in print function, we must use escape sequence \\ to force print \\ and \". "

print(sampleText2)




Example:
The following example demonstrate using escape sequence to include triple double quotes.

let threeDoubleQuotes = """
To include triple double quotes we can use escape sequence before the triple double quotes as shown below
    Escaping the first quote \"""
Alternatively, we can also escape each double quotes as shown below
    Escaping all three quotes \"\"\"
End
"""

print(threeDoubleQuotes)





There are other escape sequence which we will not use frequently.
  • The first type of escape sequence is line feed. To break and force a new line in a text, we can use \n. This is however not necessary when using multiline text, we just hit enter to a new line and the system will convert the new line to \n. Print function also automatically appended \n. You can however include a \n in the middle of text to break a print string into 2 lines.
  • The second type of escape sequence is horizontal tab. We use the escape sequence \t to represent horizontal tab.
  • We do not find the other escape sequence such as \0 (null character) and \r (return carriage) useful.

Creating String & Character

Create a String Constant

If we want a string value to remain the same and unchanged, then we should create a string constant. String constant is immutable (not changeable).

We can create a string constant by using the following syntax:

let <constant_name> = <string literals/string expression>

Example:

let stringConstant = "This is a string constant"



We can also declared the constant first and assign the data later:

let <constant_name>:String

To assign the constant use the syntax:
<constant_name> = <string literals/string expression>

Please note that the method above is not encourage as it make the code unsafe when we forget to initialize the string. Please use the method above only when absolutely necessary.

Example:

let stringConstant2: String

stringConstant2 = "This constant can only be assigned ONCE"



We can also create constant using addition sign.

Example:

let name = "Dave"
let stringConstant3 = "Hello!" + " " + name + "! " + "How are you?"



Create a String Variable

If we want a string value that can be change as and when required, then we should create a string variable. String variable is mutable.
String variable can be created using the following syntax:

var <variable_name> = <string literals/string expression>

Example:

var stringVariable1 = "Default string value"
stringVariable1

stringVariable1 = "New string value"
stringVariable1




Alternatively, we can also declared the variable first and assign data later

var <variable_name>:String

To assign the constant use the syntax:

<variable_name> = <string literals/string expression>


Example:

var stringVariable2: String

stringVariable2 = "This string can be changed anytime."
stringVariable2

stringVariable2 = "Latest update."
stringVariable2




Please note that the method above is not encourage as it make the code unsafe when we forget to initialize the string. For variables, we should initialize the variable immediately with empty string.


To create string variable with initialization, use the syntax below:

var <variable_name> = String()

Using the above construct, we can create a variable with initialization. The initialization process will create an empty string. We can then assign any string to variable later. This is the safer way to code. Please note that the above construct do not work with constant because constant variable is immutable.

Example:

var stringVariable3 = String()
stringVariable3

stringVariable3 = "Do something"
stringVariable3



Create Empty String

We can create an empty string by just providing the double quotation:

var <variable_name> = ""

Alternatively, we can also use the syntax below. Both methods produce same effects.

var <variable_name> = String()

The methods above is much better than declaring a String without assignment. These methods ensure that the string variable has been initialized and it can be used.

Example:

var stringVariable3 = ""
var stringVariable4 = String()



To check if a string constant/variable is empty, we use the property isEmpty

Example:

stringVariable3.isEmpty
stringVariable4.isEmpty


Create Constant Character

Please note that since the data type Character do not support type inference, we must indicate the datatype during creation. Character data type only accept a single character in the Unicode.
To create a character constant, use the syntax as shown below:

let <constant_name>: Character = <character/ expression that evaluate into character>

Example:

let chConstant1: Character = "\u{23}"



We can use Unicode extended grapheme cluster to form a single character as shown below.  

Example:

let chConstant2: Character = "\u{1112}\u{1161}\u{11AB}"



Create Variable Character

To create a character variable, use the syntax as shown below:

var <variable_name>: Character = <character/ expression that evaluate into character>

Example:

var chVar1: Character = "&"



Creating String with Repeating Feature

We can also create a string with repeating feature. We can create such string by following the syntax below:

let/var <string_name> = String(repeating: "<string_to_repeat>", count: <no_of_times>)

We place the string to repeat after repeating. It can also be a character instead of string. Count refers to the number of times to repeat.

Example:

let someString140 = String(repeating: "Omega", count: 10)
print(someString140)



Using String

Empty String

To find out if the string is empty, use the isEmpty property. To use this property, follow the syntax below:

<string_constant/variable>.isEmpty

The system will return a true or false result.

Example:

let someString101 = "Say something"
let someString102 = ""

someString101.isEmpty
someString102.isEmpty



Length of String

To check the length of a string, use the count property.  To use this property, follow the syntax below:

<string_constant/variable>.count

The system will iterate through the string and display the count in integer.

Example:

let someString103 = "Say something"

someString103.count



Please note that due to the way Unicode format characters, it is no longer true that one Unicode represent one character. In some situation, we can have 2 or 3 Unicode represent one character. Therefore, we cannot simply count the number of Unicode and derived the number of characters in a string. When we use the count property, the system will iterate the entire string in order to derived the character count. This feature slow down the system especially when the string is long.


String Interpolation

As we have mentioned before, we can use string interpolation to convert other data type to String. String interpolation works with single line or multiline string.

Example:

let someNumber100 = 100
print("The number from the constant is \(someNumber100).")
print("------------------------------------")

let someNumber101 = 2.7865
let someString102 = """
Start of multiline
This is multiline text.

1. The number from another constant is \(someNumber101).
End.

"""
print(someString102)



We can also include complex expression within the string interpolation.

let someNumber103 = 100000
print("""
Complex Expression

We can include complex expression such as the example below.

   Your commission is \(someNumber103 >= 1000000 ?  Double(someNumber103) * 0.03 : Double(someNumber103) * 0.005 + 2500.0).

   Your next sales target should be \(Double(someNumber103) * 1.20).

The above demostrate how to incorporate complex expression in string interpolation.
""")



Working with String and Character

As we know a string is actually an array of characters. Therefore, we can threat a string as an array and break them down into characters. To do that we can iterate the entire string using for-in loop.

Example:

let someString11 = "Apollo"
for char in someString11 {
   print(char)
}


We can form a string using arrays of Character

let someStringArray12:[Character] = ["A","t","h","e","n", "a"]
let someString14 = String(someStringArray12)
print(someString14)



We can also transpose a string into an character array

var someStringArray15:[Character] = []

let someString16 = "Aristotle"
for index in someString16 {
   someStringArray15.append(index)
}

print(someStringArray15)

Adding or Appending String

Concatenating Strings

  • We can join strings using the plus operator (+).
  • We can join between string literals and/or string variables.

Example:

let stringSample1 = "This is a test." + " And this is the second part of a jointed string"

print(stringSample1)




Example 2: Joining between a string variable and string literals

let stringSample2 = "This is second test."

let stringSample3 = stringSample2 + " " + "Second part of second test string."

print(stringSample3)





Example 3: Join string between 2 string constant

let stringSample4 = "Hello, welcome to Swift. "

let stringSample5 = "I am your assistant."

let stringSample6 = stringSample4 + stringSample5

print(stringSample6)





To add 2 multiline strings together, please ensure that every line especially the last line ends with a line break. See example below:

let stringSample10 = """
Line 1
Line 2
"""

let stringSample11 = """
Line 3
Line 4
"""

let stringSample12 = stringSample10 + stringSample11
print(stringSample12)



To ensure proper line break in the last line, we add an empty line as shown below:

let stringSample13 = """
Line 1
Line 2

"""

let stringSample14 = """
Line 3
Line 4

"""

let stringSample15 = stringSample13 + stringSample14
print(stringSample15)



Compound Assignment in String

  • We can also join string using the operator (+=). Using this operator we can append a new string into the original string.

Example 4:

var stringSample7 = "Hello, "

stringSample7 += "Welcome to the Star Fleet."

print(stringSample7)



Example 5:

var stringSample8 = "Hello, "

let stringSample9 = "Command Center"

let space = " "

stringSample8 += "Sir." + space + "Welcome to the "

stringSample8 += stringSample9 + "."

print(stringSample8)



For multiline operation, please also ensure that the main string and additional string have line return.


var stringSample16 = """
Line 1
Line 2

"""

let stringSample17 = """
Line 3
Line 4

"""

stringSample16 += stringSample17
print(stringSample16)



Another example:

var stringSample18 = """
Line 1
Line 2

"""

// We append a new line so that we can append new string later
let stringSample19 = "Line 3" + "\n"

stringSample18 += stringSample19

stringSample18 += "Line Last"
print(stringSample18)



Append String

To append string, use the .append function as follows:

<string_variable>.append(<text_to_append>)

Please note that append only works with string variable but not constant. However, we can append an existing variable with constant string.

Example:

// Append only works with string variable
var stringSample20 = "Wow This is wonderful"
stringSample20.append("! ")
let stringSample21 = "Good to hear that."
stringSample20.append(stringSample21)



Accessing and Extracting String

Accessing Character from String

In addition to the indexing method mentioned above, we can also access the first and last character using the method listed below.

Accessing First Character

To access the first character, use the method .first. The syntax of usage is as follows:

<string>.first

Example:

var someString114 = "Supercalifragilisticexpialidocious"
someString114.first



Accessing Last Character

To access the first character, use the method .first. The syntax of usage is as follows:


<string>.last


Example:


var someString115 = "Supercalifragilisticexpialidocious"
someString115.last




Extracting String using Prefix and Suffix Method

We can also extract a portion of string using prefix and suffix method. Prefix allow us to extract a portion of the string from the beginning of the string whereas suffix allows us to extract a portion of the string from the end of the string.

The syntax for prefix is as follows:

let/var <substring> = <string>.prefix(<number_of_char>)

Example:

// Extracting first 5 and 20 characters from a string
var someString0426 = "supercalifragilisticexpialidocious"
let sub0426a = someString0426.prefix(5)
let sub0426b = someString0426.prefix(20)



We can also use index to help with the extraction of substring. We use the prefix method with additional option as shown below:

let/var <substring> = <string>.prefix(upTo: <index_in_string>)

This method allows us to extract the substring from the beginning of text up to but excluding the index of the character we specified.

To include the index of the character we specified, we use the method prefix with through option:

let/var <substring> = <string>.prefix(though: <index_in_string>)

Example:

// Setup and find the index position of x
var someString0426 = "supercalifragilisticexpialidocious"
let idxOfx = someString0426.index(of: "x")

// Extracting substring up to character x (excluding x)
let sub0426c = someString0426.prefix(upTo: idxOfx!)

// Extracting substring thorugh character x (Including x)
let sub0426d = someString0426.prefix(through: idxOfx!)



Similarly syntax for suffix is as follows:

let/var <substring> = <string>.suffix(<number_of_char>)

Example:

// Extracting LAST 5 and 20 characters from a string
var someString0426 = "supercalifragilisticexpialidocious"
let sub04262e = someString0426.suffix(5)
let sub04262f = someString0426.suffix(20)



We can also use index to help with the extraction of substring. We use the suffix method with additional option as shown below:

let/var <substring> = <string>.suffix(from: <index_in_string>)

This method allows us to extract the substring from the index we specified to the end of the text.

Example:

// Setup and find the index position of x
var someString0426 = "supercalifragilisticexpialidocious"
let idxOfx = someString0426.index(of: "x")

// Extracting substring from x (including x) to the end of text
let sub0426g = someString0426.suffix(from: idxOfx!)


Extracting String using Drop Method

We can also use dropFirst and dropLast to extract the remaining string except the first and last character. The syntax is as follows:

let <substring_name> = <string>.dropFirst()

let <substring_name> = <string>.dropLast()

Unlike the remove method, the drop method will not change the original string. It will extract all characters except the first or last character and return the result as a substring.

var someString131 = "Supercalifragilisticexpialidocious"

// Retrieve all character except first character
let exceptFirst = someString131.dropFirst()
exceptFirst
// No change in original string
someString131

let exceptLast = someString131.dropLast()
exceptLast
someString131



Instead of dropping only the first or last character, we can drop any number of character by indicating the number of character to drop. The syntax is as follows:

let <substring_name> = <string>.dropFirst(count: <no_of_char>)

let <substring_name> = <string>.dropLast(count: <no_of_char>)

See example below:

var someString147 = "supercalifragilisticexpialidocious"
let subString147A = someString147.dropFirst(5)

let subRange147 = someString147.range(of: "expialidocious")
let subDistance147 = someString147.distance(from: subRange147!.lowerBound, to: subRange147!.upperBound)
let subString147B = someString147.dropLast(subDistance147)
someString147
subString147A
subString147B



String Indexing

Similar to an array, if string is an array of characters, then we need have an index for the string. As we have learned previously, we can have situation that 2 or more Unicode formed one character. Thus, different character require different amount of memory to store. Therefore, we cannot rely on integer to index the string. Swift implement its own indexing.

The property startIndex represent the first character. The property endIndex is the position after the last index in a string. Therefore endIndex is not valid if we just call them. For empty string the startIndex is the same as endIndex.

Start Index and End Index

To reference the first character in a string, use startIndex. To extract the index use the syntax below:

let <index_name> = <string_name>.startIndex

To extract the character, use the syntax below:

let <char_name> = <string_name>.[<index_name>]

We can combine the previous construct into a single line as shown below:

let <char_name> = <string_name>.[<string_name>.startIndex]

See the example below.

let someString104 = "I Think Therefore I am"
let firstCharIndex = someString104.startIndex
let firstChar = someString104[firstCharIndex]

print("The first character is \(firstChar).")



Another example:

let someString105 = "Here is to the crazy one"
let firstChar = someString105[someString105.startIndex]

print("The first character is \(firstChar).")



End index refers to the position after the last index in a string. Therefore, the index is invalid by itself.



We can also see what contains in string index.

let someString107a = "Do something"
print(someString107a.startIndex)
print(someString107a.endIndex)



We notice that the string is based on UTF16 (Unicode 16 bit). We suspect that the compoundOffset refers to the position.

For an empty string, the start index is the same as end index.

let someString106 = ""
someString106.startIndex == someString106.endIndex



Index Of

We can use the method index:of to locate the position of the character we are looking:

let <index_name> = <string_name>.index(of: "<character>")

Example:

var someString146 = "supercalifragilisticexpialidocious"

// locate the position of x
let xPositionIndex = someString146.index(of: "x")
// to confirm the index is accurate
someString146[xPositionIndex!]



Index Before and After

We can however, use the method index(before:) and index(after:) to find character. To use index(before:) using the syntax below:

let <index_name> = <string_name>.index(before: <another_end_index_reference>)

For example to extract the last character, we can use .index(before: <string_name>.endIndex). See example below:

let someString107 = "Do something"
let lastCharIndex = someString107.index(before: someString107.endIndex)
someString107[lastCharIndex]



To use .index(after:), we follow the syntax below:

let <index_name> = <string_name>.index(after: <start_index_reference>)

We can use the construct above to extract the second character in a string as shown below:

let someString108 = "Say something"
let secondCharIndex = someString108.index(after: someString108.startIndex)
someString108[secondCharIndex]



Index Offset

What happen if we want to extract the fifth character in a string. We can use .index(_:offsetBy:) method. The syntax is as follows:

let <index> = <string>.index(<begining_index>:offsetBy:<character_count>)

Please note that beginning index can be start index or it can be any index we derived earlier. Offset is computed as the number of position excluding the starting position.

Example:

let someString109 = "Supercalifragilisticexpialidocious"
let someString109StartIndex = someString109.startIndex
someString109[someString109StartIndex]

// To extract 9th character from start
// the offset will be 9 - 1 = 8
let ninthCharIndex = someString109.index(someString109StartIndex, offsetBy: 8)
someString109[ninthCharIndex]



Another example:

let someString110 = "Omnia mea mecum porto"
let someString110StartIndex = someString110.startIndex
someString110[someString110StartIndex]

// To extract the position of third word
// the offset will be 11 - 1 = 10
let thirdWordIndex = someString110.index(someString110StartIndex, offsetBy: 10)
someString110[thirdWordIndex]

// To extract the 4th character of thrid word, offset is 3
let extractIndex = someString110.index(thirdWordIndex, offsetBy: 3)
someString110[extractIndex]



As illustrated above, the beginning index may not be the start of the string when using offset. We calculate the position of the third word and then use offset from the starting of third word instead of the beginning of string.

We have an alternative construct where we add additional limit so that we will not exceed the hound of the string. The syntax is as follows

let <index> = <string>.index(<begining_index> :offsetBy:<character_count> :limitBy:<index_limit>)

Example:

let someString140 = "Omnia mea mecum porto"
let someString140StartIndex = someString140.startIndex
someString140[someString140StartIndex]

// To extract the position of third word
// the offset will be 11 - 1 = 10
let thirdWordIndex = someString140.index(someString140.startIndex, offsetBy: 10, limitedBy: someString140.endIndex)
someString140[thirdWordIndex!]

// To extract the last character of third word, offset is 5-1 = 4
let extractIndex = someString140.index(thirdWordIndex!, offsetBy: 4, limitedBy: someString140.endIndex)
someString140[extractIndex!]



Indices

The property .indices refers to a collection of index. We use this property to iterate each index as shown below:

let someString111 = "Supercalifragilisticexpialidocious"
for index in someString111.indices {
   print(someString111[index], terminator: "")
}



So, there are 2 ways to print character by character. We can use with indices property or without indices property. See example below:

let someString112 = "Supercalifragilisticexpialidocious"

print("First Example")
for char in someString112 {
   print(char, terminator: "")
}

print("\n")
print("Second Example")

for index in someString112.indices {
   print(someString112[index], terminator: "")
}



The main differences between the 2 method is that the first method iterate through the character whereas the second example iterate through indices. If we would just print index for the second example, we would have show the index like the screenshot below:



Distance

We can compute the length of a portion of a string if we have the position of the start and end index of the substring. The distance method will return the character count between the start and end index position.

The syntax is as follows:

let <count_holder> = <string>.distance(from: <start_index>, to: <end_index>)

We can use the distance as offset for other use of index.

Example:
The following example, will count the position of the start of each word and we will also compute the length of each word. We use index and offset to find the position of each word, then we compute the length of each word by computing the distance between each starting word less space.

var someString134 = "Omnia Mea Mecum Porto"

let startOfSecondWord = someString134.index(someString134.startIndex, offsetBy: 6)
someString134[startOfSecondWord]

let startOfThirdWord = someString134.index(startOfSecondWord, offsetBy: 4)
someString134[startOfThirdWord]

let startOfFourthWord = someString134.index(someString134.endIndex, offsetBy: -5)
someString134[startOfFourthWord]

someString134.count == someString134.distance(from: someString134.startIndex, to: someString134.endIndex)

let firstWordCount = someString134.distance(from: someString134.startIndex, to: startOfSecondWord) - 1
let secondWordCount = someString134.distance(from: startOfSecondWord, to: startOfThirdWord) - 1
let thirdWordCount = someString134.distance(from: startOfThirdWord, to: startOfFourthWord) - 1
let lastWordCount = someString134.distance(from: startOfFourthWord, to: someString134.endIndex)



Please also note that if the compute the distance from startIndex to endIndex. The distance is the same as the string count.

let someString141 = "Supercalifragilisticexpialidocious"
someString141.count == someString141.distance(from: someString141.startIndex, to: someString141.endIndex)



Please note that we can also use similar properties and method for any collection type such as arrays, dictionary or sets.


Range

Instead of using start index and end index all the time, we can set the range with a starting index and ending index.

Example:

let someString142 = "Supercalifragilisticexpialidocious"
let someRange142a = someString142.startIndex..<someString142.endIndex
someString142[someRange142a]



Another example extracting a word:
let someString143 = "Omnia mea mecum porto"
// Get index of third word
let indexOfThirdWord = someString143.index(someString143.startIndex, offsetBy: 10, limitedBy: someString143.endIndex)!
// get the range from the start of third word and offset 5 characters away offset = 5-1 = 4
let someRange143 = indexOfThirdWord...someString143.index(indexOfThirdWord, offsetBy: 4, limitedBy: someString143.endIndex)!
// Show the string using the range
someString143[someRange143]



Range Method

We can use range method to extract the range for a substring. Yes, instead of counting the offset like the example above, we can use the range method to extract the range of the substring we are looking for. The syntax is as follows:

let <range_name> = <string>.range(of: "<substring_to_search>")

Example:

let someString144 = "Omnia mea mecum porto"

let mecumRange = someString144.range(of: "mecum")
let mecumSubstring = someString144[mecumRange!]



If the substring appear multiple times in a string, we can use the range method together with the option to search backward. See example below:

let someString145 = "Supercalifragilisticexpialidocious"
// get the range if word li by searching from backward
let someRange145 = someString145.range(of: "li", options: .backwards)

// what we want is to get the string after li
// so we find the upperbound of the string
let someRange145UpperBound = someRange145!.upperBound
someString145[someRange145UpperBound]

// get the substring after li to the end of string
// expected result is "docious:
let subString145 = someString145[someRange145UpperBound..<someString145.endIndex]



SubString

While accessing and extracting string using various methods, some method will return a modified version of the string. The return string is not actually a String but it is a substring. Substring can perform most the function as String. However substring is created as a derivative. The memory for substring is temporary. If we want to keep the substring for permanent use, we need to convert the substring to string using String(<substring>).

Example:

var someString135 = "supercalifragilisticexpialidocious"
let subStringRange135 = someString135.index(someString135.startIndex, offsetBy: 5)...someString135.index(before: someString135.endIndex)
let subString135 = someString135[subStringRange135]

let someString136 = String(subString135)

Modifying String

Inserting String

We can use 2 method of inserting string. We can use insert(_:at:) or insert(contentOf:at:). The syntax is as follows:

<string>.insert(<character>, at: <string_index>)

<string>.insert(contentOf: <string_to_insert>, at: <string_index>)  

Please note that the first method only accepts a single character whereas the second method accepts any string. Please refer to the example below:

var someString113 = "Hello"
someString113.insert("!", at: someString113.endIndex)

someString113.insert(contentsOf: " How are you?", at: someString113.endIndex)

someString113.insert(contentsOf: "Commander! ", at: someString113.index(someString113.startIndex, offsetBy: 7))



Removing String

We can use 2 method of removing string. We can use remove(at:) or removeSubrange(_:). The syntax is as follows:

<string>.remove(at: <string_index>)

<string>.removeSubrange(<range_fr_start_to_end_index>)  

The first method only remove only one character at the specified position. The second method remove a range of character form the string. We must define the range which is from the starting position in string index to the end position in string index.

Please refer to the example below:

var someString116 = "Hello"

// insert ! at the last
someString116.insert("!", at: someString116.endIndex)
// insert How are you? including an empty space in front at teh end of string
someString116.insert(contentsOf: " How are you?", at: someString116.endIndex)

// Remove character ! after Hello
someString116.remove(at: someString116.index(someString116.startIndex, offsetBy: 5))
someString116

// Insert Commander! after a spacing after Hello
someString116.insert(contentsOf: "Commander! ", at: someString116.index(someString116.startIndex, offsetBy: 6))

// Calculate the index starting position of sub string "How are you"
let indexSubString1 = someString116.index(someString116.endIndex, offsetBy: -13)

// Set the range from the starting position to the last of string
let subStringRange = indexSubString1 ..< someString116.endIndex

// Remove How are are? from the string
someString116.removeSubrange(subStringRange)
someString116



Let's have another example where we remove a word in a sentences.

var someString117 = "Hi, stranger! Welcome to the enterprise."
someString117.insert(contentsOf: "!", at: someString117.index(someString117.startIndex, offsetBy: 2))
print(someString117)

// To remove ", stranger!"
// Computing start and end index
let startingIndex = someString117.index(someString117.startIndex, offsetBy: 3)
let endingIndex = someString117.index(someString117.startIndex, offsetBy: 13)
// Computing range
let rangeOfTextRemove = startingIndex...endingIndex

// Actual removal
someString117.removeSubrange(rangeOfTextRemove)
print(someString117)



Removing Character from String

We can also remove the first and last character of the string using the syntax below:

<string>.removeFirst()

To remove the last character use the syntax below:

<string>.removeLast()

See example below:

var someString118 = "Supercalifragilisticexpialidocious"

someString118.removeFirst()
someString118

someString118.removeLast()
someString118



Removing All

We can also reset the string variable to an empty string using the method removeAll. The syntax is as follows:

<string>.removeAll()

Example:

var someString132 = "Omnia mea mecum porto"
let temp = someString132
someString132.removeAll()
someString132



Replace String

We can replace some character or string using the replaceSubrange method. The syntax is as follows:

<string>.replaceSubrange(<range_to_be_replace>, with: <char/string_to_repalce>)

Example:

var someString149 = "supercalifragilisticexpialidocious"

// We want to replace the first 5 character "super" with "uber"
someString149.replaceSubrange(someString149.startIndex...someString149.index(someString149.startIndex, offsetBy: 4), with: "uber")
someString149



Split Words

Swift also contains powerful method such as split to separate the word from a string. The syntax to use the method is as follows:

let <substringArray> = <string>.split(separator: "<separator_in_char/str>")

The return result is an array of substring. Besides single space, we can use any separator such as comma or tab.

Example:

var someString150 = "Omnia mea mecum porto"

// separator is single space
let someWords = someString150.split(separator: " ")
// the result is an array with substring
someWords
type(of: someWords)

for word in someWords {
   print(word)
}



Please note that the function type(of:) return the data type.

To convert the array of substring to array of string use the code below:

// continue from previous code
// convert array with substring to array with string
var newStringArray = [String]()
for word in someWords {
   newStringArray.append(String(word))
}

type(of: newStringArray)



The method in modifying string can also be used in any other collection data type such as array, dictionary and sets.

Change String Capitalization

We can change the string capitalization using the method lowercased, uppercased and capitalized. Using these method, we are able to change the string to lowercase, uppercase or capitalized the string. Please note that all the methods will not change the string itself but it will return a transformed string for us to use. Since these methods will not modify the string, we can also use these method for string constant.

The syntax is as follows:

let <string_holder> = <string>.lowercased()

let <string_holder> = <string>.capitalized
let <string_holder> = <string>.uppercased()

Example:

var someString133 = "Omnia mea mecum porto"
let lowercasedString133 = someString133.lowercased()

someString133
lowercasedString133

let capitalizedString133 = someString133.capitalized
let uppercasedString133 = someString133.uppercased()

// Replace original string with capitalized string
someString133
someString133 = someString133.capitalized
someString133



Reverse String

We can reverse a string using the reverse method. This method will return a substring. However to display the substring, we must iterate through the substring. Alternatively, we can convert the substring to a string. The syntax is as follows:

let <substring> = <string>.reversed()

Example:

var someString137 = "supercalifragilisticexpialidocious"
let subString137 = someString137.reversed()
subString137
// To display substring need to iterate through the substring
for char in subString137 {
   print(char, terminator: "")
}
print("\n")
// convert substring to String
let someString138 = String(subString137)
print(someString138)



To affect change on the original string, use the method below:

var someString137 = "supercalifragilisticexpialidocious"
let subString137 = someString137.reversed()

someString137 = String(subString137)

Comparing and Finding String

We can use equal or not equal comparison operator to compare against each string. Please note that for 2 string to be equal it must have identical character including spaces.

Example:

let someString119 = "Supercalifragilisticexpialidocious"
let someString120 = "Supercalifragilisticexpialidocious"

someString119 == someString120

let someString121 = "Hi there!"
let somestring122 = "Hi  there!"

someString121 == somestring122



For extended grapheme clusters, we can compare different construction of the same character. The result is the same. Two same character constructed with different Unicode is the same.

"\u{65}"
"\u{301}"

let someString123 = "\u{65}\u{301}"
let someString124 = "\u{E9}"

someString123 == someString124

"\u{1112}"
"\u{1161}"
"\u{11AB}"

let someString125 = "\u{1112}\u{1161}\u{11AB}"
let someString126 = "\u{D55C}"

someString125 == someString126



Please note that the same character in different character set is not equivalent. For example, our normal capital letter A (Unicode:41) is not the same as the greek capital letter A (Unicode:391).

let normalLetterA = "\u{41}"
let greekLetterA = "\u{0391}"
normalLetterA == greekLetterA


Comparing Prefix and Suffix

We can also use hasPrefix or hasSuffix to find strings with certain prefix or suffix. The 2 methods will return a boolean value true or false. The syntax for check for prefix and suffix is as follows:

<string>.hasPrefix("<prefix_to_check>")

<string>.hasSuffix("<suffix_to_check>")

See example below:

let someString127 = "biochemical"
someString127.hasPrefix("bio")

let someString128 = "technophile"
someString128.hasSuffix("phile")



More detail example:

let someString129 = ["biology","cosmology","anthropology", "epidemiology", "psychology", "microbiology","pharmacology", "epistemology", "anthropology", "physiology", "biotechnology", "biometeorology"]

print("Words that start with bio")
for words in someString129 {
   if words.hasPrefix("bio") {
       print(words)
   }
}



Another example on listing suffix:

let someString130 = ["biology","cosmology","anthropology", "epidemiology", "psychology", "microbiology","pharmacology", "epistemology", "anthropology", "physiology", "biotechnology", "biometeorology"]

print("Words that end with logy")
for words in someString130 {
   if words.hasSuffix("logy") {
       print(words)
   }
}



Compare  Substring using Contains

We can check and compare if a set of characters existing in a string. The method to check is contain. The syntax is as follows:

let <boolean_name> = <string>.contains("<substring_to_search>")

The contain method will return a true or false value.

Example:

var someString148 = "supercalifragilisticexpialidocious"

someString148.contains("listic")
someString148.contains("super")
someString148



Additional Example:

var someString0426b = "This is the test for string"
let sub0426h = someString0426b.contains("test")
let sub0426i = someString0426b.contains("string")
let sub0426j = someString0426b.contains("super")



***

No comments:

Post a Comment