Your code doesn't do any range checking:
let str = "test"
let start = str.index(str.startIndex, offsetBy: 7)
Write a function that tests the length of the string first. In fact, you could create an extension on String that lets you use integer subscripts, and returns a Character?
:
extension String {
//Allow string[Int] subscripting. WARNING: Slow O(n) performance
subscript(index: Int) -> Character? {
guard index < self.count else { return nil }
return self[self.index(self.startIndex, offsetBy: index)]
}
}
This code:
var str = "test"
print("str[7] = \"\(str[7])\"")
Would display:
str[7] = "nil"
##EDIT:
Be aware, as Alexander pointed out in a comment below, that the subscript extension above has up to O(n)
performance (it takes longer and longer as the index value goes up, up to the length of the string.)
If you need to loop through all the characters in a string code like this:
for i in str.count { doSomething(string: str[i]) }
would have O(n^2)
(Or n-squared
) performance, which is really, really bad. in that case, you should instead first convert the string to an array of characters:
let chars = Array(str.characters)
for i in chars.count { doSomething(string: chars[i]) }
or
for aChar in chars { //do something with aChar }
With that code you pay the O(n)
time cost of converting the string to an array of characters once, and then you can do operations on the array of characters with maximum speed. The downside of that approach is that it would more than double the memory requirements.