205

How can I convert a String "Hello" to an Array ["H","e","l","l","o"] in Swift?

In Objective-C I have used this:

NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[myString length]];
for (int i=0; i < [myString length]; i++) {
    NSString *ichar  = [NSString stringWithFormat:@"%c", [myString characterAtIndex:i]];
    [characters addObject:ichar];
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Mr.KLD
  • 2,632
  • 2
  • 16
  • 26

14 Answers14

451

It is even easier in Swift:

let string : String = "Hello  "
let characters = Array(string)
println(characters)
// [H, e, l, l, o,  , , ,  , ]

This uses the facts that

  • an Array can be created from a SequenceType, and
  • String conforms to the SequenceType protocol, and its sequence generator enumerates the characters.

And since Swift strings have full support for Unicode, this works even with characters outside of the "Basic Multilingual Plane" (such as ) and with extended grapheme clusters (such as , which is actually composed of two Unicode scalars).


Update: As of Swift 2, String does no longer conform to SequenceType, but the characters property provides a sequence of the Unicode characters:

let string = "Hello  "
let characters = Array(string.characters)
print(characters)

This works in Swift 3 as well.


Update: As of Swift 4, String is (again) a collection of its Characters:

let string = "Hello  "
let characters = Array(string)
print(characters)
// ["H", "e", "l", "l", "o", " ", "", "", " ", ""]
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 2
    Do you have any idea why trying to join (`let joined = ", ".join(characters);`) the array results in an `'String' is not identical to 'Character'` error? – Mohamad Jan 03 '15 at 21:55
  • 3
    @Mohamad: Enumerating a string produces a sequence of characters, but `", ".join(...)` expects an array of strings. devxoul's answer below shows how you could split into an array of strings. – Martin R Jan 03 '15 at 22:07
  • failed with emoji group: `` – TomSawyer Dec 11 '15 at 11:03
  • @TomSawyer: Why do you think that is fails? Note that `` counts as a *single* Unicode grapheme cluster (and that is what `string.characters` represents), compare http://stackoverflow.com/questions/26862282/swift-countelements-return-incorrect-value-when-count-flag-emoji/26863367#26863367. – Martin R Dec 11 '15 at 12:09
  • This emoji is a group of few unicode character, if you separate them by characters will return wrong result. – TomSawyer Dec 11 '15 at 19:56
  • `` is a sequence of four Regional_Indicator characters. According to the Unicode standard this is a *single* grapheme cluster. – Martin R Dec 11 '15 at 20:18
  • @TomSawyer: Have a look at http://stackoverflow.com/questions/39104152/how-to-know-if-two-emojis-will-be-displayed-as-one-emoji if you want `` to be counted as two "characters" (even if it is a single Swift `Character` aka grapheme cluster). – Martin R Aug 24 '16 at 12:48
  • I wonder what time/space complexity impact this has... is `characters` a copy of string basically? seems kind of lame having to copy the string into a different format just to be able to index the characters. – Fonix Feb 28 '17 at 06:42
  • 2
    @Fonix: `characters` is a collection and a *view* on the strings characters. Creating an array from the characters makes a copy. – Of course can access the characters directly: `for i in string.characters.indices { print(string.characters[i]) }` or just `for c in string.characters { print(c) }` – Martin R Feb 28 '17 at 06:52
  • 2
    @Fonix: ... On the other hand, random indexing into strings can be slow and it can be advantageous to create an array with all characters once. Example: http://stackoverflow.com/questions/40371929/slow-swift-string-performance. – Martin R Feb 28 '17 at 06:55
  • Argument or string does not confirm to expected type sequence – Muhammad Zeshan Mazhar Jun 19 '17 at 05:46
  • @zeeshanDar: What is your code? Which Xcode version are you using? – Martin R Jun 19 '17 at 06:44
  • @zeeshanDar: Xcode 8.3.3. is Swift 3, so you have to use the Swift 2/3 version: `let characters = Array(string.characters)` – Martin R Jun 19 '17 at 06:48
  • Oh. My bad. How do I upgrade? –  Aug 13 '17 at 16:08
  • 2
    @DaniSpringer: Swift 4 is currently in beta, you'll need Xcode 9 beta: https://developer.apple.com/swift/resources/. – Martin R Aug 13 '17 at 16:10
  • @TomSawyer: Swift 4 (Xcode 9) implements Unicode 9, and now `Array("")` returns an array of two characters: `["", ""]`. – Martin R Dec 12 '17 at 12:04
  • This creates [String.Element] type, which is not suitable for further operation – Shrikant Phadke Feb 10 '21 at 12:53
  • @ShrikantPhadke: Can you be more specific? Not suitable for which operation? It creates a `[Character]`, if you want a `[String]` then you'll find that e.g. in devxoul's answer. – Martin R Feb 10 '21 at 13:02
  • Yes, I was expecting [String]. So below solution would be fine. let str1 = strHelloWorld.map { String($0) } or let str2 = strHelloWorld.map(String.init) or var str3 : [String] = [] for s in strHelloWorld { strarr4.append(String(s)) } – Shrikant Phadke Feb 11 '21 at 06:11
134

Edit (Swift 4)

In Swift 4, you don't have to use characters to use map(). Just do map() on String.

let letters = "ABC".map { String($0) }
print(letters) // ["A", "B", "C"]
print(type(of: letters)) // Array<String>

Or if you'd prefer shorter: "ABC".map(String.init) (2-bytes )

Edit (Swift 2 & Swift 3)

In Swift 2 and Swift 3, You can use map() function to characters property.

let letters = "ABC".characters.map { String($0) }
print(letters) // ["A", "B", "C"]

Original (Swift 1.x)

Accepted answer doesn't seem to be the best, because sequence-converted String is not a String sequence, but Character:

$ swift
Welcome to Swift!  Type :help for assistance.
  1> Array("ABC")
$R0: [Character] = 3 values {
  [0] = "A"
  [1] = "B"
  [2] = "C"
}

This below works for me:

let str = "ABC"
let arr = map(str) { s -> String in String(s) }

Reference for a global function map() is here: http://swifter.natecook.com/func/map/

vacawama
  • 150,663
  • 30
  • 266
  • 294
devxoul
  • 2,128
  • 1
  • 16
  • 13
37

There is also this useful function on String: components(separatedBy: String)

let string = "1;2;3"
let array = string.components(separatedBy: ";")
print(array) // returns ["1", "2", "3"]

Works well to deal with strings separated by a character like ";" or even "\n"

Frederic Adda
  • 5,905
  • 4
  • 56
  • 71
19

For Swift version 5.3 its easy as:

let string = "Hello world"
let characters = Array(string)

print(characters)

// ["H", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]

Ali Hamad
  • 599
  • 6
  • 12
15

Updated for Swift 4

Here are 3 ways.

//array of Characters
let charArr1 = [Character](myString)

//array of String.element
let charArr2 = Array(myString)

for char in myString {
  //char is of type Character
}

In some cases, what people really want is a way to convert a string into an array of little strings with 1 character length each. Here is a super efficient way to do that:

//array of String
var strArr = myString.map { String($0)}

Swift 3

Here are 3 ways.

let charArr1 = [Character](myString.characters)
let charArr2 = Array(myString.characters)
for char in myString.characters {
  //char is of type Character
}

In some cases, what people really want is a way to convert a string into an array of little strings with 1 character length each. Here is a super efficient way to do that:

var strArr = myString.characters.map { String($0)}

Or you can add an extension to String.

extension String {
   func letterize() -> [Character] {
     return Array(self.characters)
  }
}

Then you can call it like this:

let charArr = "Cat".letterize()
ScottyBlades
  • 12,189
  • 5
  • 77
  • 85
7

for the function on String: components(separatedBy: String)

in Swift 5.1

have change to:

string.split(separator: "/")

koen
  • 5,383
  • 7
  • 50
  • 89
Fat Panda
  • 161
  • 1
  • 9
7

An easy way to do this is to map the variable and return each Character as a String:

let someText = "hello"

let array = someText.map({ String($0) }) // [String]

The output should be ["h", "e", "l", "l", "o"].

pkamb
  • 33,281
  • 23
  • 160
  • 191
atolite
  • 71
  • 2
  • 2
4

Martin R answer is the best approach, and as he said, because String conforms the SquenceType protocol, you can also enumerate a string, getting each character on each iteration.

let characters = "Hello"
var charactersArray: [Character] = []

for (index, character) in enumerate(characters) {
    //do something with the character at index
    charactersArray.append(character)
}

println(charactersArray)
Alberto Barrera
  • 329
  • 1
  • 4
  • 2
    Or just `for character in characters { charactersArray.append(character)}` without the `enumeration()` – Tieme Nov 14 '14 at 13:40
3
    let string = "hell0"
    let ar = Array(string.characters)
    print(ar)
William Hu
  • 15,423
  • 11
  • 100
  • 121
  • There were no changes between Swift 2 and 3 with respect to this issue. This solution is identical to the Swift 2 version in https://stackoverflow.com/a/25921323/1187415. – Martin R Aug 13 '17 at 16:13
3

In Swift 4, as String is a collection of Character, you need to use map

let array1 = Array("hello") // Array<Character>
let array2 = Array("hello").map({ "\($0)" }) // Array<String>
let array3 = "hello".map(String.init) // Array<String>
onmyway133
  • 45,645
  • 31
  • 257
  • 263
2

Suppose you have four text fields otpOneTxt, otpTwoTxt, otpThreeTxt, otpFourTxt and a string getOtp.

let getup = "5642"
let array = self.getOtp.map({ String($0) })
                
otpOneTxt.text = array[0] //5
otpTwoTxt.text = array[1] //6
otpThreeTxt.text = array[2] //4
otpFourTxt.text = array[3] //2
koen
  • 5,383
  • 7
  • 50
  • 89
Davender Verma
  • 503
  • 2
  • 12
1

You can also create an extension:

var strArray = "Hello, playground".Letterize()

extension String {
    func Letterize() -> [String] {
        return map(self) { String($0) }
    }
}
fabrizioM
  • 46,639
  • 15
  • 102
  • 119
1
func letterize() -> [Character] {
    return Array(self.characters)
}
0
let str = "cdcd"
let characterArr = str.reduce(into: [Character]()) { result, letter in
    result.append(letter)
}
print(characterArr)
//["c", "d", "c", "d"]
Manisha
  • 11