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