So for-in and .forEach() do not work on Range<String.Index> and I can see why: it's because it needs the original string to move:
let s = "xxxxxxx12345yyyyy"
let a = s.index(s.startIndex, offsetBy: 7)
let b = s.index(s.endIndex, offsetBy: -5)
let r = a ..< b
// how to iterate through r?
// for-in and .forEach() do not work. I see why: because the original string is needed to move
//for i in r { // Protocol 'Sequence' requires that 'String.Index' conform to 'Strideable'
// print(i)
//}
//
//r.forEach { // Referencing instance method 'forEach' on 'Range' requires that 'String.Index' conform to 'Strideable'
// print($0)
//}
// this works, but it's clumsy
var i = a
while i < b {
print(s[i])
i = s.index(after: i)
}
// does something like this already exist?
struct StringIndexRangeIterator: Sequence, IteratorProtocol {
private let string: String
private var at: String.Index
private let end: String.Index
init(_ s: String, range: Range<String.Index>) {
string = s
at = range.lowerBound
end = range.upperBound
}
mutating func next() -> String.Index? {
if at >= end {
return nil
} else {
defer { at = string.index(after: at) }
return at
}
}
}
extension String {
func iterator(of range: Range<String.Index>) -> StringIndexRangeIterator {
StringIndexRangeIterator(self, range: range)
}
}
// now it's nice and easy to iterate
for i in s.iterator(of: r) {
print(s[i])
}
let s = "xxxxxxx12345yyyyy"
let a = s.index(s.startIndex, offsetBy: 7)
let b = s.index(s.endIndex, offsetBy: -5)
let r = s[a ..< b]
for each in r {
print(each)
}
let s = "xxxxxxx12345yyyyy"
let a = s.index(s.startIndex, offsetBy: 7)
let b = s.index(s.endIndex, offsetBy: -5)
let r = a ..< b
// or just s[r] if you don't need the index itself, as @masters3d said above.
for i in s.indices[r] {
print("index \(i) has char \(s[i]) ")
}
I would have gone with s[r].indices rather than s.indices[r]. In String's case they're going to work, but it's not required that Self.Index and Self.Indices.Index are the same type, or that they line up, whereas Self.Index and Self.SubSequence.Index are guaranteed to be interchangeable.
Oops, I’m incorrect! I was looking under Indices for the constraint, but it’s under Index instead. (Along with a bunch of other redundant constraints.) I do wonder why the extension and the struct have different behavior here; that seems like a bug.