Hi, I am trying to understand String indices exactly. Seems like that example does not work correctly as it prints this:
Would anyone be so kind and clarify it for me? Thank You
Hi, I am trying to understand String indices exactly. Seems like that example does not work correctly as it prints this:
Would anyone be so kind and clarify it for me? Thank You
What would you expect it to print?
thought its gonna print the letter before the last one. How could I do that instead?
print(string[indexLast])
Swifts String
does not work as many people expect:
"Unicode"[2] == "i"
Is not even allowed by the compiler (without libraries beyond the stdlib), because String
uses a special index which is not a simple Int
.
It's not hard to add such a subscript, though.
Oh, wait, that looks like a different issue
No, that wouldn't be an index; what you want is string[indexLast]
.
Edit: No, actually you want to use the index before indexLast
;-)
what about printing some middle letter?
String
s are hard — but to be fair, many other languages with a model that is easier to work with can produce incorrect results ;-)
You can (should ;-) use the index manipulation methods to get arbitrary elements.
For convenience, I suggest to create extension methods for String
(actually, I would use the Collection
protocols). That way, you don't have to repeat the string.
-part that often.
The trick is in identifying that string.index return back a type which is not integer, it is String.Index type
let string = "twojkiar"
//You are getting type back as String.index and not integer
let indexLast = string.index(before: string.endIndex)
type(of: indexLast)
print (string[indexLast])
Now, string.endIndex is one past the last character in the string so before endIndex gives you the last index
If you want to manipulate at want to get Character at a given string index then you can do so by doing something like:
string [string.index(string.startIndex, offsetBy: (string.count/2))]
offset as the name suggest is how much you want to move in either direction of starting point, we start at startIndex so we can go only positive direction
Your indexLast
is the position of the last character in your string
, because endIndex
is right after the last character. Here is the documentation of endIndex
.
All you need to do is offset the index by one more, and print the character at the index instead of the index itself:
let string = "twojkiar"
let indexOfA = string.index(string.endIndex, offsetBy: -2)
print(string[indexOfA])
Here is the documentation of index(_:offsetBy:)
.
To print the last element of the string use:
print(string[indexLast])
Your original expression printed out "indexLast
" as an object in and of itself, not the part of "string
" it referred to.
BTW, the String
type is a bidirectional collection. This means that its index-pack type, i.e. String.Indices
, is also a bidirectional collection. That means you can simply get the last index value by:
let indexLast = string.indices.last!
Of course, looking at that pattern, you can get the last element of the string similarly:
print(string.last!)
Again, this only works when the collection type conforms to BidirectionalCollection
, and you have to test that .last
isn't nil
(or assure yourself that it won't be nil
under your circumstances, and accept the consequences if you're wrong).
If you really need to consider a string like a collection of characters, and randomly access arbitrary parts in the middle, you could convert your String
to a randomly accessible collection (like e.g an Array
) of Character
elements, and access its elements through an Int
index:
let string = ... // some string from somewhere
let chars = Array(string)
print(chars[chars.count/2])
print(chars.last)
print(chars[...])
However, except for some toy examples that often come up in coding tutorials, this kind of use case is pretty uncommon. You most likely want to walk (iterate through) the string, or use indices that are the result of some calculation based on actual string parsing and calculations.