3

I learned that Swift strings cannot be indexed by integer values. I remembered it and I use the rule. But I've never fully understood the mechanic behind it.

The explanation of from the official document is as follows

"Different characters can require different amounts of memory to store, so in order to determine which Character is at a particular position, you must iterate over each Unicode scalar from the start or end of that String. For this reason, Swift strings cannot be indexed by integer values"

I've read it several times, I still don't quite get the point. Can someone explain me a bit more why Swift String cannot be indexed by integer values?

Many Thanks

4
  • developer.apple.com/library/ios/documentation/Swift/Conceptual/… - this is topic you are talking about. As for me, will be pretty hard to explain more clear than when you read this topic from start to end. Commented Jun 16, 2016 at 13:19
  • 4
    Quick hint, not a complete explanation: Swift strings respect unicode, and some emojis, for example, are "composed" characters, they appear as one character but they actually can use up to four real characters - it's just that we don't see it, the several characters are composed into one when displayed. That's why we can't rely on the "index" of a character in a string in Swift. Commented Jun 16, 2016 at 13:20
  • @Moritz, that explains why you can't implement integer indexing by mapping it to the corresponding unicode code points as they appear in memory, but it doesn't prevent the implementation of an interface where myString[8] corresponds to the 7th canonical symbol in myString. Your hint is absolutely right, but the above is why I—and probably others too—look up the question. Commented Feb 18, 2018 at 14:40
  • 1
    “For this reason, Swift strings cannot be indexed by integer values.” ... I find it funny that we end up using integers, to calculate indexes from startIndex, regardless, e.g., the third character starts at let start = string.index(string.startIndex, offsetBy: 2). I understand the rationale, but it doesn’t justify the added complexity. Commented Dec 11, 2019 at 22:53

1 Answer 1

1

A string is stored in memory as an array of bytes.

A given character can require 1 to 4 bytes for the basic codepoint, plus any number of combining diacritical mark.

For example, é requires 2 bytes.

Now, if you have the strings efgh and éfgh, to access the second character (f), for the first string, the character is in the byte array at index 1, for the second string, it is at index 2.

In order to know that, you need to inspect the first character. For accessing any character based on its index, you need to go through all the previous characters to know how many bytes each takes.

Sign up to request clarification or add additional context in comments.

5 Comments

Characters can be way wider than 4 bytes. "g͇̫͛͆̾ͫ̑͆".characters.count == 1 && "g͇̫͛͆̾ͫ̑͆".lengthOfBytes(using: .utf8) == 17
@BrianNickel yes, I forgot you can add diacritics and combine them. (In my example, é also exists as a stand alone character). But each codepoint is encoded in 1 to 4 bytes.
@BrianNickel, why couldn't we just define index 0 as Swift's startIndex and index N > 0 as Swift's index(startIndex, offsetBy: N)? In your example, does Swift provide a way to access e and ´ individually by index?
@Mike Things have definitely changed inside Swift since we had this discussion. A lot. String now conforms to Collection and can be indexed like you describe.
@Mike With regards to your question, it depends on the string. é can be represented two ways, either as \u{e9} (accented e) or e\u{301} (e with an accent combination character). In the former case, it's one character and one scalar but two bytes of UTF-8. You can access the individual bytes with str.utf8. In the latter case, it's two scalars, two utf-16 characters, and 3 utf-8 bytes. There are views for accessing each of these: repl.it/repls/DownrightInsubstantialInterpreter

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.