str[i], str[i..<j], str[i...j]
👉 replit
extension String {
/// ⭐ example: `str[5]`
public subscript(_ i: Int) -> String? {
// ⭐ guard: non-empty string, non-negative index
guard !isEmpty, i >= 0 else { return nil }
// ⭐ safe bound
let bound = index(before: endIndex) // ⭐ Note: `endIndex` is NOT safe
// ⭐ guard: startIndex <= index < endIndex
guard let index = index(startIndex, offsetBy: i, limitedBy: bound) else {
return nil
}
// ⭐ Character -> String
return String(self[index])
}
/// example: `str[2..<5]`
public subscript(bounds: Range<Int>) -> String? {
// ⭐ guard: empty string
guard !isEmpty else { return nil } // empty string -> nil
// ⭐ guard: 0 <= m < n
let (m, n) = (bounds.lowerBound, bounds.upperBound)
guard 0 <= m, m < n else { return nil } // negative index -> nil
// ⭐ guard: i < endIndex, j <= endIndex
let bound = index(before: endIndex)
guard let i = index(startIndex, offsetBy: m, limitedBy: bound) else {
return nil
}
guard let j = index(startIndex, offsetBy: n, limitedBy: endIndex) else {
return nil
}
// i, j are in safe range
return String(self[i..<j])
}
/// example: `str[2...5]`
public subscript(bounds: ClosedRange<Int>) -> String? {
// ⭐ guard: empty string
guard !isEmpty else { return nil } // empty string -> nil
// ⭐ guard: 0 <= m < n
let (m, n) = (bounds.lowerBound, bounds.upperBound)
guard 0 <= m, m <= n else { return nil } // negative index -> nil
// ⭐ guard: i < endIndex, j <= endIndex
let bound = index(before: endIndex)
guard let i = index(startIndex, offsetBy: m, limitedBy: bound) else {
return nil
}
guard let j = index(startIndex, offsetBy: n, limitedBy: bound) else {
return nil
}
// i, j are in safe range
return String(self[i...j])
}
}
Last updated
Was this helpful?