Get nth character of a string in Swift programming language

后端 未结 30 1951
一整个雨季
一整个雨季 2020-11-22 01:26

How can I get the nth character of a string? I tried bracket([]) accessor with no luck.

var string = \"Hello, world!\"

var firstChar = string[         


        
相关标签:
30条回答
  • 2020-11-22 01:52

    Swift 5.3

    I think this is very elegant. Kudos at Paul Hudson of "Hacking with Swift" for this solution:

    @available (macOS 10.15, * )
    extension String {
        subscript(idx: Int) -> String {
            String(self[index(startIndex, offsetBy: idx)])
        }
    }
    
    

    Then to get one character out of the String you simply do:

    var string = "Hello, world!"
    
    var firstChar = string[0] // No error, returns "H" as a String
    
    0 讨论(0)
  • 2020-11-22 01:53

    Swift 4.2

    This answer is ideal because it extends String and all of its Subsequences (Substring) in one extension

    public extension StringProtocol {
        
        public subscript (i: Int) -> Element {
            return self[index(startIndex, offsetBy: i)]
        }
    
        public subscript (bounds: CountableClosedRange<Int>) -> SubSequence {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[start...end]
        }
        
        public subscript (bounds: CountableRange<Int>) -> SubSequence {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[start..<end]
        }
        
        public subscript (bounds: PartialRangeUpTo<Int>) -> SubSequence {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[startIndex..<end]
        }
        
        public subscript (bounds: PartialRangeThrough<Int>) -> SubSequence {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[startIndex...end]
        }
        
        public subscript (bounds: CountablePartialRangeFrom<Int>) -> SubSequence {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            return self[start..<endIndex]
        }
    }
    

    Usage

    var str = "Hello, playground"
    
    print(str[5...][...5][0])
    // Prints ","
    
    0 讨论(0)
  • 2020-11-22 01:54

    Get & Set Subscript (String & Substring) - Swift 4.2

    Swift 4.2, Xcode 10

    I based my answer off of @alecarlson's answer. The only big difference is you can get a Substring or a String returned (and in some cases, a single Character). You can also get and set the subscript. Lastly, mine is a bit more cumbersome and longer than @alecarlson's answer and as such, I suggest you put it in a source file.


    Extension:

    public extension String {
        public subscript (i: Int) -> Character {
            get {
                return self[index(startIndex, offsetBy: i)]
            }
            set (c) {
                let n = index(startIndex, offsetBy: i)
                replaceSubrange(n...n, with: "\(c)")
            }
        }
        public subscript (bounds: CountableRange<Int>) -> Substring {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return self[start ..< end]
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(start ..< end, with: s)
            }
        }
        public subscript (bounds: CountableClosedRange<Int>) -> Substring {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return self[start ... end]
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(start ... end, with: s)
            }
            
        }
        public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(endIndex, offsetBy: -1)
                return self[start ... end]
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(endIndex, offsetBy: -1)
                replaceSubrange(start ... end, with: s)
            }
        }
        public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
            get {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return self[startIndex ... end]
            }
            set (s) {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(startIndex ... end, with: s)
            }
        }
        public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
            get {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return self[startIndex ..< end]
            }
            set (s) {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(startIndex ..< end, with: s)
            }
        }
        
        public subscript (i: Int) -> String {
            get {
                return "\(self[index(startIndex, offsetBy: i)])"
            }
            set (c) {
                let n = index(startIndex, offsetBy: i)
                self.replaceSubrange(n...n, with: "\(c)")
            }
        }
        public subscript (bounds: CountableRange<Int>) -> String {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return "\(self[start ..< end])"
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(start ..< end, with: s)
            }
        }
        public subscript (bounds: CountableClosedRange<Int>) -> String {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return "\(self[start ... end])"
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(start ... end, with: s)
            }
            
        }
        public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(endIndex, offsetBy: -1)
                return "\(self[start ... end])"
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(endIndex, offsetBy: -1)
                replaceSubrange(start ... end, with: s)
            }
        }
        public subscript (bounds: PartialRangeThrough<Int>) -> String {
            get {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return "\(self[startIndex ... end])"
            }
            set (s) {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(startIndex ... end, with: s)
            }
        }
        public subscript (bounds: PartialRangeUpTo<Int>) -> String {
            get {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return "\(self[startIndex ..< end])"
            }
            set (s) {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(startIndex ..< end, with: s)
            }
        }
        
        public subscript (i: Int) -> Substring {
            get {
                return Substring("\(self[index(startIndex, offsetBy: i)])")
            }
            set (c) {
                let n = index(startIndex, offsetBy: i)
                replaceSubrange(n...n, with: "\(c)")
            }
        }
    }
    public extension Substring {
        public subscript (i: Int) -> Character {
            get {
                return self[index(startIndex, offsetBy: i)]
            }
            set (c) {
                let n = index(startIndex, offsetBy: i)
                replaceSubrange(n...n, with: "\(c)")
            }
            
        }
        public subscript (bounds: CountableRange<Int>) -> Substring {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return self[start ..< end]
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(start ..< end, with: s)
            }
        }
        public subscript (bounds: CountableClosedRange<Int>) -> Substring {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return self[start ... end]
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(start ... end, with: s)
            }
        }
        public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(endIndex, offsetBy: -1)
                return self[start ... end]
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(endIndex, offsetBy: -1)
                replaceSubrange(start ... end, with: s)
            }
            
        }
        public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
            get {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return self[startIndex ... end]
            }
            set (s) {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(startIndex ..< end, with: s)
            }
        }
        public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
            get {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return self[startIndex ..< end]
            }
            set (s) {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(startIndex ..< end, with: s)
            }
        }
        public subscript (i: Int) -> String {
            get {
                return "\(self[index(startIndex, offsetBy: i)])"
            }
            set (c) {
                let n = index(startIndex, offsetBy: i)
                replaceSubrange(n...n, with: "\(c)")
            }
        }
        public subscript (bounds: CountableRange<Int>) -> String {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return "\(self[start ..< end])"
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(start ..< end, with: s)
            }
        }
        public subscript (bounds: CountableClosedRange<Int>) -> String {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return "\(self[start ... end])"
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(start ... end, with: s)
            }
            
        }
        public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
            get {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(endIndex, offsetBy: -1)
                return "\(self[start ... end])"
            }
            set (s) {
                let start = index(startIndex, offsetBy: bounds.lowerBound)
                let end = index(endIndex, offsetBy: -1)
                replaceSubrange(start ... end, with: s)
            }
        }
        public subscript (bounds: PartialRangeThrough<Int>) -> String {
            get {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return "\(self[startIndex ... end])"
            }
            set (s) {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(startIndex ... end, with: s)
            }
        }
        public subscript (bounds: PartialRangeUpTo<Int>) -> String {
            get {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                return "\(self[startIndex ..< end])"
            }
            set (s) {
                let end = index(startIndex, offsetBy: bounds.upperBound)
                replaceSubrange(startIndex ..< end, with: s)
            }
        }
        
        public subscript (i: Int) -> Substring {
            get {
                return Substring("\(self[index(startIndex, offsetBy: i)])")
            }
            set (c) {
                let n = index(startIndex, offsetBy: i)
                replaceSubrange(n...n, with: "\(c)")
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:54

    Swift 5.1.3:

    Add a String extension:

    extension String {
    
     func stringAt(_ i: Int) -> String { 
       return String(Array(self)[i]) 
     } 
    
     func charAt(_ i: Int) -> Character { 
      return Array(self)[i] 
     } 
    }
    
    let str = "Teja Kumar"
    let str1: String = str.stringAt(2)  //"j"
    let str2: Character = str.charAt(5)  //"k"
    
    0 讨论(0)
  • 2020-11-22 01:55

    Swift 4

    String(Array(stringToIndex)[index]) 
    

    This is probably the best way of solving this problem one-time. You probably want to cast the String as an array first, and then cast the result as a String again. Otherwise, a Character will be returned instead of a String.

    Example String(Array("HelloThere")[1]) will return "e" as a String.

    (Array("HelloThere")[1] will return "e" as a Character.

    Swift does not allow Strings to be indexed like arrays, but this gets the job done, brute-force style.

    0 讨论(0)
  • 2020-11-22 01:55

    Here's an extension you can use, working with Swift 3.1. A single index will return a Character, which seems intuitive when indexing a String, and a Range will return a String.

    extension String {
        subscript (i: Int) -> Character {
            return Array(self.characters)[i]
        }
        
        subscript (r: CountableClosedRange<Int>) -> String {
            return String(Array(self.characters)[r])
        }
        
        subscript (r: CountableRange<Int>) -> String {
            return self[r.lowerBound...r.upperBound-1]
        }
    }
    

    Some examples of the extension in action:

    let string = "Hello"
    
    let c1 = string[1]  // Character "e"
    let c2 = string[-1] // fatal error: Index out of range
    
    let r1 = string[1..<4] // String "ell"
    let r2 = string[1...4] // String "ello"
    let r3 = string[1...5] // fatal error: Array index is out of range
    


    n.b. You could add an additional method to the above extension to return a String with a single character if wanted:

    subscript (i: Int) -> String {
        return String(self[i])
    }
    

    Note that then you would have to explicitly specify the type you wanted when indexing the string:

    let c: Character = string[3] // Character "l"
    let s: String = string[0]    // String "H"
    
    0 讨论(0)
提交回复
热议问题