Get nth character of a string in Swift programming language

SwiftStringCollectionsCharacterSubscript

Swift Problem Overview


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

var string = "Hello, world!"

var firstChar = string[0] // Throws error

> ERROR: 'subscript' is unavailable: cannot subscript String with an Int, see the documentation comment for discussion

Swift Solutions


Solution 1 - Swift

Attention: Please see Leo Dabus' answer for a proper implementation for Swift 4 and Swift 5.

Swift 4 or later

The Substring type was introduced in Swift 4 to make substrings faster and more efficient by sharing storage with the original string, so that's what the subscript functions should return.

Try it out here
extension StringProtocol {
    subscript(offset: Int) -> Character { self[index(startIndex, offsetBy: offset)] }
    subscript(range: Range<Int>) -> SubSequence {
        let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
        return self[startIndex..<index(startIndex, offsetBy: range.count)]
    }
    subscript(range: ClosedRange<Int>) -> SubSequence {
        let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
        return self[startIndex..<index(startIndex, offsetBy: range.count)]
    }
    subscript(range: PartialRangeFrom<Int>) -> SubSequence { self[index(startIndex, offsetBy: range.lowerBound)...] }
    subscript(range: PartialRangeThrough<Int>) -> SubSequence { self[...index(startIndex, offsetBy: range.upperBound)] }
    subscript(range: PartialRangeUpTo<Int>) -> SubSequence { self[..<index(startIndex, offsetBy: range.upperBound)] }
}

To convert the Substring into a String, you can simply do String(string[0..2]), but you should only do that if you plan to keep the substring around. Otherwise, it's more efficient to keep it a Substring.

It would be great if someone could figure out a good way to merge these two extensions into one. I tried extending StringProtocol without success, because the index method does not exist there. Note: This answer has been already edited, it is properly implemented and now works for substrings as well. Just make sure to use a valid range to avoid crashing when subscripting your StringProtocol type. For subscripting with a range that won't crash with out of range values you can use this implementation


Why is this not built-in?

The error message says "see the documentation comment for discussion". Apple provides the following explanation in the file UnavailableStringAPIs.swift:

> Subscripting strings with integers is not available. > > The concept of "the ith character in a string" has > different interpretations in different libraries and system > components. The correct interpretation should be selected > according to the use case and the APIs involved, so String > cannot be subscripted with an integer. > > Swift provides several different ways to access the character > data stored inside strings. > > - String.utf8 is a collection of UTF-8 code units in the > string. Use this API when converting the string to UTF-8. > Most POSIX APIs process strings in terms of UTF-8 code units. > > - String.utf16 is a collection of UTF-16 code units in > string. Most Cocoa and Cocoa touch APIs process strings in > terms of UTF-16 code units. For example, instances of > NSRange used with NSAttributedString and > NSRegularExpression store substring offsets and lengths in > terms of UTF-16 code units. > > - String.unicodeScalars is a collection of Unicode scalars. > Use this API when you are performing low-level manipulation > of character data. > > - String.characters is a collection of extended grapheme > clusters, which are an approximation of user-perceived > characters. > > Note that when processing strings that contain human-readable text, > character-by-character processing should be avoided to the largest extent > possible. Use high-level locale-sensitive Unicode algorithms instead, for example, > String.localizedStandardCompare(), > String.localizedLowercaseString, > String.localizedStandardRangeOfString() etc.

Solution 2 - Swift

Swift 5.2
let str = "abcdef"
str[1 ..< 3] // returns "bc"
str[5] // returns "f"
str[80] // returns ""
str.substring(fromIndex: 3) // returns "def"
str.substring(toIndex: str.length - 2) // returns "abcd"

You will need to add this String extension to your project (it's fully tested):

extension String {

    var length: Int {
        return count
    }

    subscript (i: Int) -> String {
        return self[i ..< i + 1]
    }

    func substring(fromIndex: Int) -> String {
        return self[min(fromIndex, length) ..< length]
    }

    func substring(toIndex: Int) -> String {
        return self[0 ..< max(0, toIndex)]
    }

    subscript (r: Range<Int>) -> String {
        let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
                                            upper: min(length, max(0, r.upperBound))))
        let start = index(startIndex, offsetBy: range.lowerBound)
        let end = index(start, offsetBy: range.upperBound - range.lowerBound)
        return String(self[start ..< end])
    }
}

Even though Swift always had out of the box solution to this problem (without String extension, which I provided below), I still would strongly recommend using the extension. Why? Because it saved me tens of hours of painful migration from early versions of Swift, where String's syntax was changing almost every release, but all I needed to do was to update the extension's implementation as opposed to refactoring the entire project. Make your choice.

let str = "Hello, world!"
let index = str.index(str.startIndex, offsetBy: 4)
str[index] // returns Character 'o'

let endIndex = str.index(str.endIndex, offsetBy:-2)
str[index ..< endIndex] // returns String "o, worl"

String(str.suffix(from: index)) // returns String "o, world!"
String(str.prefix(upTo: index)) // returns String "Hell"

Solution 3 - Swift

I just came up with this neat workaround

var firstChar = Array(string)[0]

Solution 4 - Swift

Xcode 11 β€’ Swift 5.1

You can extend StringProtocol to make the subscript available also to the substrings:

extension StringProtocol {
    subscript(_ offset: Int)                     -> Element     { self[index(startIndex, offsetBy: offset)] }
    subscript(_ range: Range<Int>)               -> SubSequence { prefix(range.lowerBound+range.count).suffix(range.count) }
    subscript(_ range: ClosedRange<Int>)         -> SubSequence { prefix(range.lowerBound+range.count).suffix(range.count) }
    subscript(_ range: PartialRangeThrough<Int>) -> SubSequence { prefix(range.upperBound.advanced(by: 1)) }
    subscript(_ range: PartialRangeUpTo<Int>)    -> SubSequence { prefix(range.upperBound) }
    subscript(_ range: PartialRangeFrom<Int>)    -> SubSequence { suffix(Swift.max(0, count-range.lowerBound)) }
}

extension LosslessStringConvertible {
    var string: String { .init(self) }
}

extension BidirectionalCollection {
    subscript(safe offset: Int) -> Element? {
        guard !isEmpty, let i = index(startIndex, offsetBy: offset, limitedBy: index(before: endIndex)) else { return nil }
        return self[i]
    }
}

Testing

let test = "Hello USA πŸ‡ΊπŸ‡Έ!!! Hello Brazil πŸ‡§πŸ‡·!!!"
test[safe: 10]   // "πŸ‡ΊπŸ‡Έ"
test[11]   // "!"
test[10...]   // "πŸ‡ΊπŸ‡Έ!!! Hello Brazil πŸ‡§πŸ‡·!!!"
test[10..<12]   // "πŸ‡ΊπŸ‡Έ!"
test[10...12]   // "πŸ‡ΊπŸ‡Έ!!"
test[...10]   // "Hello USA πŸ‡ΊπŸ‡Έ"
test[..<10]   // "Hello USA "
test.first   // "H"
test.last    // "!"

// Subscripting the Substring
 test[...][...3]  // "Hell"

// Note that they all return a Substring of the original String.
// To create a new String from a substring
test[10...].string  // "πŸ‡ΊπŸ‡Έ!!! Hello Brazil πŸ‡§πŸ‡·!!!"

Solution 5 - Swift

No indexing using integers, only using String.Index. Mostly with linear complexity. You can also create ranges from String.Index and get substrings using them.

Swift 3.0

let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.index(before: someString.endIndex)]
let charAtIndex = someString[someString.index(someString.startIndex, offsetBy: 10)]

let range = someString.startIndex..<someString.index(someString.startIndex, offsetBy: 10)
let substring = someString[range]

Swift 2.x

let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.endIndex.predecessor()]
let charAtIndex = someString[someString.startIndex.advanceBy(10)]

let range = someString.startIndex..<someString.startIndex.advanceBy(10)
let subtring = someString[range]

Note that you can't ever use an index (or range) created from one string to another string

let index10 = someString.startIndex.advanceBy(10)

//will compile
//sometimes it will work but sometimes it will crash or result in undefined behaviour
let charFromAnotherString = anotherString[index10]
 

Solution 6 - Swift

Swift 4

let str = "My String"

String at index

let index = str.index(str.startIndex, offsetBy: 3)
String(str[index])    // "S"

Substring

let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)
String(str[startIndex...endIndex])     // "Strin"

First n chars

let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[..<startIndex])    // "My "

Last n chars

let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[startIndex...])    // "String"

Swift 2 and 3

str = "My String"

**String At Index **

Swift 2

let charAtIndex = String(str[str.startIndex.advancedBy(3)])  // charAtIndex = "S"

Swift 3

str[str.index(str.startIndex, offsetBy: 3)]

SubString fromIndex toIndex

Swift 2

let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)] // subStr = "Strin"

Swift 3

str[str.index(str.startIndex, offsetBy: 3)...str.index(str.startIndex, offsetBy: 7)]

First n chars

let first2Chars = String(str.characters.prefix(2)) // first2Chars = "My"

Last n chars

let last3Chars = String(str.characters.suffix(3)) // last3Chars = "ing"

Solution 7 - Swift

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

NB: I just wanted to add, this will return a String as pointed out in the comments. I think it might be unexpected for Swift users, but often I need a String to use in my code straight away and not a Character type, so it does simplify my code a little bit avoiding a conversion from Character to String later.

Solution 8 - Swift

If you see Cannot subscript a value of type 'String'... use this extension:

Swift 3

extension String {
    subscript (i: Int) -> Character {
        return self[self.characters.index(self.startIndex, offsetBy: i)]
    }

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

    subscript (r: Range<Int>) -> String {
        let start = index(startIndex, offsetBy: r.lowerBound)
        let end = index(startIndex, offsetBy: r.upperBound)
        return self[start..<end]
    }
    
    subscript (r: ClosedRange<Int>) -> String {
        let start = index(startIndex, offsetBy: r.lowerBound)
        let end = index(startIndex, offsetBy: r.upperBound)
        return self[start...end]
    }
}

Swift 2.3

extension String {
    subscript(integerIndex: Int) -> Character {
        let index = advance(startIndex, integerIndex)
        return self[index]
    }

    subscript(integerRange: Range<Int>) -> String {
        let start = advance(startIndex, integerRange.startIndex)
        let end = advance(startIndex, integerRange.endIndex)
        let range = start..<end
        return self[range]
    }
}

Source: http://oleb.net/blog/2014/07/swift-strings/

Solution 9 - Swift

Swift 2.0 as of Xcode 7 GM Seed

var text = "Hello, world!"

let firstChar = text[text.startIndex.advancedBy(0)] // "H"

For the nth character, replace 0 with n-1.

Edit: Swift 3.0

text[text.index(text.startIndex, offsetBy: 0)]


n.b. there are simpler ways of grabbing certain characters in the string

e.g. let firstChar = text.characters.first

Solution 10 - Swift

Swift 2.2 Solution:

The following extension works in Xcode 7, this is a combination of this solution and Swift 2.0 syntax conversion.

extension String {
    subscript(integerIndex: Int) -> Character {
        let index = startIndex.advancedBy(integerIndex)
        return self[index]
    }
    
    subscript(integerRange: Range<Int>) -> String {
        let start = startIndex.advancedBy(integerRange.startIndex)
        let end = startIndex.advancedBy(integerRange.endIndex)
        let range = start..<end
        return self[range]
    }
}

Solution 11 - Swift

The swift string class does not provide the ability to get a character at a specific index because of its native support for UTF characters. The variable length of a UTF character in memory makes jumping directly to a character impossible. That means you have to manually loop over the string each time.

You can extend String to provide a method that will loop through the characters until your desired index

extension String {
    func characterAtIndex(index: Int) -> Character? {
        var cur = 0
        for char in self {
            if cur == index {
                return char
            }
            cur++
        }
        return nil
    }
}

myString.characterAtIndex(0)!

Solution 12 - Swift

As an aside note, there are a few functions applyable directly to the Character-chain representation of a String, like this:

var string = "Hello, playground"
let firstCharacter = string.characters.first // returns "H"
let lastCharacter = string.characters.last // returns "d"

The result is of type Character, but you can cast it to a String.

Or this:

let reversedString = String(string.characters.reverse())
// returns "dnuorgyalp ,olleH" 

:-)

Solution 13 - Swift

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.

Solution 14 - Swift

You can do it by convert String into Array and get it by specific index using subscript as below

var str = "Hello"
let s = Array(str)[2]
print(s)

Solution 15 - Swift

My very simple solution:

Swift 4.1:

let myString = "Test string"
let index = 0
let firstCharacter = myString[String.Index(encodedOffset: index)]

Swift 5.1:

let firstCharacter = myString[String.Index.init(utf16Offset: index, in: myString)]

Solution 16 - Swift

I just had the same issue. Simply do this:

var aString: String = "test"
var aChar:unichar = (aString as NSString).characterAtIndex(0)

Solution 17 - Swift

Swift3

You can use subscript syntax to access the Character at a particular String index.

let greeting = "Guten Tag!"
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index] // a

Visit https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html

or we can do a String Extension in Swift 4

extension String {
    func getCharAtIndex(_ index: Int) -> Character {
        return self[self.index(self.startIndex, offsetBy: index)]
    }
}

USAGE:

let foo = "ABC123"
foo.getCharAtIndex(2) //C

Solution 18 - Swift

By now, subscript(_:) is unavailable. As well as we can't do this

str[0] 

with string.We have to provide "String.Index" But, how can we give our own index number in this way, instead we can use,

string[str.index(str.startIndex, offsetBy: 0)]

Solution 19 - Swift

In Swift 5 without extension to the String :

var str = "ABCDEFGH"
for char in str {
if(char == "C") { }
}

Above Swift code as same as that Java code :

int n = 8;
var str = "ABCDEFGH"
for (int i=0; i<n; i++) {
if (str.charAt(i) == 'C') { }
}

Solution 20 - Swift

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"

Solution 21 - Swift

My solution is in one line, supposing cadena is the string and 4 is the nth position that you want:

let character = cadena[advance(cadena.startIndex, 4)]

Simple... I suppose Swift will include more things about substrings in future versions.

Solution 22 - Swift

Swift 3: another solution (tested in playground)

extension String {
    func substr(_ start:Int, length:Int=0) -> String? {
        guard start > -1 else {
            return nil
        }
        
        let count = self.characters.count - 1
  
        guard start <= count else {
            return nil
        }
    
        let startOffset = max(0, start)
        let endOffset = length > 0 ? min(count, startOffset + length - 1) : count
        
        return self[self.index(self.startIndex, offsetBy: startOffset)...self.index(self.startIndex, offsetBy: endOffset)]
    }
}

Usage:

let txt = "12345"

txt.substr(-1) //nil
txt.substr(0) //"12345"
txt.substr(0, length: 0) //"12345"
txt.substr(1) //"2345"
txt.substr(2) //"345"
txt.substr(3) //"45"
txt.substr(4) //"5"
txt.substr(6) //nil
txt.substr(0, length: 1) //"1"
txt.substr(1, length: 1) //"2"
txt.substr(2, length: 1) //"3"
txt.substr(3, length: 1) //"4"
txt.substr(3, length: 2) //"45"
txt.substr(3, length: 3) //"45"
txt.substr(4, length: 1) //"5"
txt.substr(4, length: 2) //"5"
txt.substr(5, length: 1) //nil
txt.substr(5, length: -1) //nil
txt.substr(-1, length: -1) //nil

Solution 23 - Swift

Swift 4.2 or later

Range and partial range subscripting using String's indices property

As variation of @LeoDabus nice answer, we may add an additional extension to DefaultIndices with the purpose of allowing us to fall back on the indices property of String when implementing the custom subscripts (by Int specialized ranges and partial ranges) for the latter.

extension DefaultIndices {
    subscript(at: Int) -> Elements.Index { index(startIndex, offsetBy: at) }
}

// Moving the index(_:offsetBy:) to an extension yields slightly
// briefer implementations for these String extensions.
extension String {
    subscript(range: Range<Int>) -> SubSequence {
        let start = indices[range.lowerBound]
        return self[start..<indices[start...][range.count]]
    }
    subscript(range: ClosedRange<Int>) -> SubSequence {
        let start = indices[range.lowerBound]
        return self[start...indices[start...][range.count]]
    }
    subscript(range: PartialRangeFrom<Int>) -> SubSequence {
        self[indices[range.lowerBound]...]
    }
    subscript(range: PartialRangeThrough<Int>) -> SubSequence {
        self[...indices[range.upperBound]]
    }
    subscript(range: PartialRangeUpTo<Int>) -> SubSequence {
        self[..<indices[range.upperBound]]
    }
}

let str = "foo bar baz bax"
print(str[4..<6]) // "ba"
print(str[4...6]) // "bar"
print(str[4...])  // "bar baz bax"
print(str[...6])  // "foo bar"
print(str[..<6])  // "foo ba"

Thanks @LeoDabus for the pointing me in the direction of using the indices property as an(other) alternative to String subscripting!

Solution 24 - Swift

Best way which worked for me is:

var firstName = "Olivia"
var lastName = "Pope"

var nameInitials.text = "\(firstName.prefix(1))" + "\    (lastName.prefix(1))"

Output:"OP"

Solution 25 - Swift

We have subscript which will very useful here

But String subscript will take param as String.Index so most of the people gets confuse here how to pass String.Index to get details how to form String.Index as per our requirement please look at below documentation Apple Documentation

Here i have created one extension method to get nth character in string

extension String {
    subscript(i: Int) -> String {
        return  i < count ? String(self[index(startIndex, offsetBy: i)]) : ""
    }
}

Usage

let name = "Narayana Rao"
print(name[11]) //o
print(name[1]) //a
print(name[0]) //N
print(name[30]) //""

if you pass index which is out of bounds of String count it will return empty String

Solution 26 - Swift

Update for swift 2.0 subString

public extension String {
    public subscript (i: Int) -> String {
        return self.substringWithRange(self.startIndex..<self.startIndex.advancedBy(i + 1))
    }
    
    public subscript (r: Range<Int>) -> String {
        get {
            return self.substringWithRange(self.startIndex.advancedBy(r.startIndex)..<self.startIndex.advancedBy(r.endIndex))
        }
    }

}

Solution 27 - Swift

I think that a fast answer for get the first character could be:

let firstCharacter = aString[aString.startIndex]

It's so much elegant and performance than:

let firstCharacter = Array(aString.characters).first

But.. if you want manipulate and do more operations with strings you could think create an extension..here is one extension with this approach, it's quite similar to that already posted here:

extension String {
var length : Int {
	return self.characters.count
}

subscript(integerIndex: Int) -> Character {
	let index = startIndex.advancedBy(integerIndex)
	return self[index]
}

subscript(integerRange: Range<Int>) -> String {
	let start = startIndex.advancedBy(integerRange.startIndex)
	let end = startIndex.advancedBy(integerRange.endIndex)
	let range = start..<end
	return self[range]
}

}

BUT IT'S A TERRIBLE IDEA!!

The extension below is horribly inefficient. Every time a string is accessed with an integer, an O(n) function to advance its starting index is run. Running a linear loop inside another linear loop means this for loop is accidentally O(n2) β€” as the length of the string increases, the time this loop takes increases quadratically.

Instead of doing that you could use the characters's string collection.

Solution 28 - Swift

Swift 3

extension String {

    public func charAt(_ i: Int) -> Character {
        return self[self.characters.index(self.startIndex, offsetBy: i)]
    }

    public subscript (i: Int) -> String {
        return String(self.charAt(i) as Character)
    }

    public subscript (r: Range<Int>) -> String {
        return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound))
    }

    public subscript (r: CountableClosedRange<Int>) -> String {
        return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound))
    }

}

Usage

let str = "Hello World"
let sub = str[0...4]

Helpful Programming Tips and Tricks (written by me)

Solution 29 - Swift

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"

Solution 30 - Swift

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)")
        }
    }
}

Solution 31 - Swift

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 ","

Solution 32 - Swift

Swift's String type does not provide a characterAtIndex method because there are several ways a Unicode string could be encoded. Are you going with UTF8, UTF16, or something else?

You can access the CodeUnit collections by retrieving the String.utf8 and String.utf16 properties. You can also access the UnicodeScalar collection by retrieving the String.unicodeScalars property.

In the spirit of NSString's implementation, I'm returning a unichar type.

extension String
{
    func characterAtIndex(index:Int) -> unichar
    {
        return self.utf16[index]
    }
    
    // Allows us to use String[index] notation
    subscript(index:Int) -> unichar
    {
        return characterAtIndex(index)
    }
}

let text = "Hello Swift!"
let firstChar = text[0]

Solution 33 - Swift

In order to feed the subject and show swift subscript possibilities, here's a little string "substring-toolbox" subscript based

These methods are safe and never go over string indexes

extension String {
    // string[i] -> one string char
    subscript(pos: Int) -> String { return String(Array(self)[min(self.length-1,max(0,pos))]) }
    
    // string[pos,len] -> substring from pos for len chars on the left
    subscript(pos: Int, len: Int) -> String { return self[pos, len, .pos_len, .left2right] }
    
    // string[pos, len, .right2left] -> substring from pos for len chars on the right
    subscript(pos: Int, len: Int, way: Way) -> String { return self[pos, len, .pos_len, way] }
    
    // string[range] -> substring form start pos on the left to end pos on the right
    subscript(range: Range<Int>) -> String { return self[range.startIndex, range.endIndex, .start_end, .left2right] }
    
    // string[range, .right2left] -> substring start pos on the right to end pos on the left
    subscript(range: Range<Int>, way: Way) -> String { return self[range.startIndex, range.endIndex, .start_end, way] }
    
    var length: Int { return countElements(self) }
    enum Mode { case pos_len, start_end }
    enum Way { case left2right, right2left }
    subscript(var val1: Int, var val2: Int, mode: Mode, way: Way) -> String {
        if mode == .start_end {
            if val1 > val2 { let val=val1 ; val1=val2 ; val2=val }
            val2 = val2-val1
        }
        if way == .left2right {
            val1 = min(self.length-1, max(0,val1))
            val2 = min(self.length-val1, max(1,val2))
        } else {
            let val1_ = val1
            val1 = min(self.length-1, max(0, self.length-val1_-val2 ))
            val2 = max(1, (self.length-1-val1_)-(val1-1) )
        }
        return self.bridgeToObjectiveC().substringWithRange(NSMakeRange(val1, val2))
            
        //-- Alternative code without bridge --
        //var range: Range<Int> = pos...(pos+len-1)
        //var start = advance(startIndex, range.startIndex)
        //var end = advance(startIndex, range.endIndex)
        //return self.substringWithRange(Range(start: start, end: end))
    }
}


println("0123456789"[3]) // return "3"

println("0123456789"[3,2]) // return "34"

println("0123456789"[3,2,.right2left]) // return "56"

println("0123456789"[5,10,.pos_len,.left2right]) // return "56789"

println("0123456789"[8,120,.pos_len,.right2left]) // return "01"

println("0123456789"[120,120,.pos_len,.left2right]) // return "9"

println("0123456789"[0...4]) // return "01234"

println("0123456789"[0..4]) // return "0123"

println("0123456789"[0...4,.right2left]) // return "56789"

println("0123456789"[4...0,.right2left]) // return "678" << because ??? range can wear endIndex at 0 ???

Solution 34 - Swift

A python-like solution, which allows you to use negative index,

var str = "Hello world!"
str[-1]        // "!"

could be:

extension String {
    subscript (var index:Int)->Character{
        get {
            let n = distance(self.startIndex, self.endIndex)
            index %= n
            if index < 0 { index += n }
            return self[advance(startIndex, index)]
        }
    }
}

By the way, it may be worth it to transpose the whole python's slice notation

Solution 35 - Swift

You can also convert String to Array of Characters like that:

let text = "My Text"
let index = 2
let charSequence = text.unicodeScalars.map{ Character($0) }
let char = charSequence[index]

This is the way to get char at specified index in constant time.

The example below doesn't run in constant time, but requires linear time. So If You have a lot of searching in String by index use the method above.

let char = text[text.startIndex.advancedBy(index)]

Solution 36 - Swift

I wanted to point out that if you have a large string and need to randomly access many characters from it, you may want to pay the extra memory cost and convert the string to an array for better performance:

// Pay up front for O(N) memory
let chars = Array(veryLargeString.characters)

for i in 0...veryLargeNumber {
    // Benefit from O(1) access
    print(chars[i])
}

Solution 37 - Swift

In Swift 3 without extensions to the String class, as simple as I can make it!

let myString = "abcedfg"
let characterLocationIndex = myString.index(myString.startIndex, offsetBy: 3)
let myCharacter = myString[characterLocationIndex]

myCharacter is "3" in this example.

Solution 38 - Swift

Using characters would do the job. You can quickly convert the String to an array of characters that can be manipulated by the CharacterView methods.

Example:

let myString = "Hello World!"
let myChars  = myString.characters

(full CharacterView doc)

(tested in Swift 3)

Solution 39 - Swift

There's an alternative, explained in String manifesto

extension String : BidirectionalCollection {
    subscript(i: Index) -> Character { return characters[i] }
}

Solution 40 - Swift

Get the first letter:

first(str) // retrieve first letter

More here: http://sketchytech.blogspot.com/2014/08/swift-pure-swift-method-for-returning.html

Solution 41 - Swift

You could use SwiftString (https://github.com/amayne/SwiftString) to do this.

"Hello, world!"[0] // H
"Hello, world!"[0...4] // Hello

DISCLAIMER: I wrote this extension

Solution 42 - Swift

Allows Negative Indices

Its always useful not always having to write string[string.length - 1] to get the last character when using a subscript extension. This (Swift 3) extension allows for negative indices, Range and CountableClosedRange.

extension String {
    var count: Int { return self.characters.count }

    subscript (i: Int) -> Character {
        // wraps out of bounds indices
        let j = i % self.count
        // wraps negative indices
        let x = j < 0 ? j + self.count : j
    
        // quick exit for first
        guard x != 0 else {
            return self.characters.first!
        }
    
        // quick exit for last
        guard x != count - 1 else {
            return self.characters.last!
        }
    
        return self[self.index(self.startIndex, offsetBy: x)]
    }

    subscript (r: Range<Int>) -> String {
        let lb = r.lowerBound
        let ub = r.upperBound
    
        // quick exit for one character
        guard lb != ub else { return String(self[lb]) }
    
        return self[self.index(self.startIndex, offsetBy: lb)..<self.index(self.startIndex, offsetBy: ub)]
    }

    subscript (r: CountableClosedRange<Int>) -> String {
        return self[r.lowerBound..<r.upperBound + 1]
    }
}

How you can use it:

var text = "Hello World"

text[-1]    // d
text[2]     // l
text[12]    // e
text[0...4] // Hello
text[0..<4] // Hell

For the more thorough Programmer: Include a guard against empty Strings in this extension

subscript (i: Int) -> Character {
    guard self.count != 0 else { return '' }
    ...
}

subscript (r: Range<Int>) -> String {
    guard self.count != 0 else { return "" }
    ...
}

 

Solution 43 - Swift

Swift 3:

extension String {
    func substring(fromPosition: UInt, toPosition: UInt) -> String? {
        guard fromPosition <= toPosition else {
            return nil
        }
        
        guard toPosition < UInt(characters.count) else {
            return nil
        }
        
        let start = index(startIndex, offsetBy: String.IndexDistance(fromPosition))
        let end   = index(startIndex, offsetBy: String.IndexDistance(toPosition) + 1)
        let range = start..<end
        
        return substring(with: range)
    }
}

"ffaabbcc".substring(fromPosition: 2, toPosition: 5) // return "aabb"

Solution 44 - Swift

Include this extension in your project

  extension String{
func trim() -> String
{
    return self.trimmingCharacters(in: NSCharacterSet.whitespaces)
}

var length: Int {
    return self.count
}

subscript (i: Int) -> String {
    return self[i ..< i + 1]
}

func substring(fromIndex: Int) -> String {
    return self[min(fromIndex, length) ..< length]
}

func substring(toIndex: Int) -> String {
    return self[0 ..< max(0, toIndex)]
}

subscript (r: Range<Int>) -> String {
    let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
                                        upper: min(length, max(0, r.upperBound))))
    let start = index(startIndex, offsetBy: range.lowerBound)
    let end = index(start, offsetBy: range.upperBound - range.lowerBound)
    return String(self[start ..< end])
}

func substring(fromIndex: Int, toIndex:Int)->String{
    let startIndex = self.index(self.startIndex, offsetBy: fromIndex)
    let endIndex = self.index(startIndex, offsetBy: toIndex-fromIndex)
    
    return String(self[startIndex...endIndex])
}

An then use the function like this

let str = "Sample-String"

let substring = str.substring(fromIndex: 0, toIndex: 0) //returns S
let sampleSubstr = str.substring(fromIndex: 0, toIndex: 5) //returns Sample

Solution 45 - Swift

Check this is Swift 4

let myString = "LOVE"

self.textField1.text = String(Array(myString)[0])
self.textField2.text = String(Array(myString)[1])
self.textField3.text = String(Array(myString)[2])
self.textField4.text = String(Array(myString)[3])

Solution 46 - Swift

Swift 5.1

Here might be the easiest solution out of all these answers.

Add this extension:

extension String {
    func retrieveFirstCharacter() -> String? {
        guard self.count > 0 else { return nil }
        let numberOfCharacters = self.count
        return String(self.dropLast(numberOfCharacters - 1))
    }
}

Solution 47 - Swift

prob one of the best and simpliest way

        let yourString = "thisString"
        print(Array(yourString)[8])

puts each letters of your string into arrrays and then you sellect the 9th one

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMohsenView Question on Stackoverflow
Solution 1 - SwiftaleclarsonView Answer on Stackoverflow
Solution 2 - SwiftnalexnView Answer on Stackoverflow
Solution 3 - SwiftJens WirthView Answer on Stackoverflow
Solution 4 - SwiftLeo DabusView Answer on Stackoverflow
Solution 5 - SwiftSulthanView Answer on Stackoverflow
Solution 6 - SwiftWarif Akhand RishiView Answer on Stackoverflow
Solution 7 - SwiftmultitudesView Answer on Stackoverflow
Solution 8 - SwiftSoftDesignerView Answer on Stackoverflow
Solution 9 - SwiftMatt Le FleurView Answer on Stackoverflow
Solution 10 - SwiftDan BeaulieuView Answer on Stackoverflow
Solution 11 - SwiftdrewagView Answer on Stackoverflow
Solution 12 - SwiftFrédéric AddaView Answer on Stackoverflow
Solution 13 - SwifthaxgadView Answer on Stackoverflow
Solution 14 - SwiftSaravit SoengView Answer on Stackoverflow
Solution 15 - SwiftLinh DaoView Answer on Stackoverflow
Solution 16 - Swiftuser3723247View Answer on Stackoverflow
Solution 17 - SwiftHamedView Answer on Stackoverflow
Solution 18 - SwiftYodagamaView Answer on Stackoverflow
Solution 19 - SwiftEmre DeğirmenciView Answer on Stackoverflow
Solution 20 - SwiftTeja Kumar BethinaView Answer on Stackoverflow
Solution 21 - SwiftJulio César Fernández MuñozView Answer on Stackoverflow
Solution 22 - SwiftPeter KreinzView Answer on Stackoverflow
Solution 23 - SwiftdfribView Answer on Stackoverflow
Solution 24 - SwiftDedeepya ReddyView Answer on Stackoverflow
Solution 25 - SwiftNarayanaView Answer on Stackoverflow
Solution 26 - SwiftYannStephView Answer on Stackoverflow
Solution 27 - SwiftignaciohugogView Answer on Stackoverflow
Solution 28 - SwiftquemefulView Answer on Stackoverflow
Solution 29 - SwiftMatt Le FleurView Answer on Stackoverflow
Solution 30 - SwiftNoah WilderView Answer on Stackoverflow
Solution 31 - SwiftNoah WilderView Answer on Stackoverflow
Solution 32 - SwiftErikView Answer on Stackoverflow
Solution 33 - SwiftLuc-OlivierView Answer on Stackoverflow
Solution 34 - SwiftJoseph MerdrignacView Answer on Stackoverflow
Solution 35 - SwiftMarcin KapustaView Answer on Stackoverflow
Solution 36 - SwiftJoseph ChenView Answer on Stackoverflow
Solution 37 - SwiftJohn PavleyView Answer on Stackoverflow
Solution 38 - SwiftStephane PaquetView Answer on Stackoverflow
Solution 39 - SwiftGeorge MaisuradzeView Answer on Stackoverflow
Solution 40 - SwiftphilippinedevView Answer on Stackoverflow
Solution 41 - SwifteurobrewView Answer on Stackoverflow
Solution 42 - SwiftJay HarrisView Answer on Stackoverflow
Solution 43 - SwiftDaniele CegliaView Answer on Stackoverflow
Solution 44 - SwiftAkilRajdhoView Answer on Stackoverflow
Solution 45 - SwiftSreekanth GView Answer on Stackoverflow
Solution 46 - SwiftJosh RView Answer on Stackoverflow
Solution 47 - Swiftbibble tripleView Answer on Stackoverflow