Fogmeister
Fogmeister

Reputation: 77641

Why do I need the string to determine the index for the Nth character?

I'd like to get a substring of a string that is just the first N characters. (10, for example).

But the string is the generated output of a function.

I'd like to do it like this...

let string = someInputString
    .someGeneratorFunctionThatReturnsAString()
    .substring(to: 10)

But I can't do this. Because the index in the substring function needs the string itself to determine where the 10th character is.

Upvotes: 2

Views: 85

Answers (2)

Jacob M. Barnard
Jacob M. Barnard

Reputation: 1367

See Gunhan's answer to question 2.

For question 1:

Long Answer: Basically, in Swift, the Collection protocol (which types like Array and String adopt) specifies performance criteria. Most notably, the start and end indices of a collection must be accessible in O(1) time. This goes for subscript access of elements as well (see text under Expected Performance heading on https://developer.apple.com/documentation/swift/collection).

Indices are memory addresses that point to either another reference or value type. For string, the indices point to Character struct values. While the value of the characters in the strings let x = "hello" and let y = "hello" might be the same, the constants x and y are different memory addresses and so are the indices that point to their respective Character struct values. So, you cannot get the substring "llo" from x and the substring "llo" from y using the same indices... that would make no sense, because the indices you would use would be specific memory addresses to only of those variables.

Architecturally, there are three entities having interplay here:

String |--hasIndicesOfType--> String.Index |--whichPointTo--> Character

(Side note: Here, Index is an associatedtype on String, which is why you see the notation String.Index if you were to, say, log one of these to the Xcode console).

In a nutshell: the answer to why the function needs the string itself is because indices of a string are memory addresses to characters of the string. String conforms to Collection to get O(1) performance on access to String's elements. Thus, the indices. Because indices are memory addresses, they only work on a given object (reference type) - which is why generic access to characters of a string only work for one string (i.e. you cannot access string A's elements with memory addresses to string B's characters... that doesn't make sense.)

In a super tiny nutshell: because String conforms to Collection.

Some helpful tutorial-ish code:

Teleology: Apparent end-goal-reasoning (aka teleological analysis) behind why String is the way it is in Swift:

Contributors to the language preferred optimizing time complexity over space complexity.

Upvotes: 1

Gunhan
Gunhan

Reputation: 7035

I just maybe understand your question wrong but nevertheless here you can substring easily:

extension String {
    func substring(to: Int) -> String? {
        return self.substring(to: self.index(self.startIndex, offsetBy: to))
    }
} 

Upvotes: 3

Related Questions