Swift: create an array of characters (Swift)

A simple question - I hope I'm trying to create a simple array of characters, something like that:

// trying to do something like this (pseudo code): let letters:[Character] = map(0..<26) { i in 'a' + i } 

and tried the following to no avail

 let a = Character("a") let z = Character("z") let r:Range<Character> = a..<z let letters:[Character] = map(a..<z) { i in i } 

I understand that Swift uses Unicode, what is the right way to do something like this?

(Note that this is not a question of interacting with the obsolete Obj-C char, strictly in Swift for testing, etc.).

+11
string ios xcode swift macos
source share
9 answers

It's a little cumbersome to get the source code of the character (i.e. 'a' in c / Obj-C) in Swift, but you can do it like this:

 let aScalars = "a".unicodeScalars let aCode = aScalars[aScalars.startIndex].value let letters: [Character] = (0..<26).map { i in Character(UnicodeScalar(aCode + i)) } 
+16
source share

Thanks for the helpful answers.

I use the single line option.

 let xs = (97...122).map({Character(UnicodeScalar($0))}) 

or

 let xs = (0..<26).map({Character(UnicodeScalar("a".unicodeScalars.first!.value + $0))}) 
+17
source share

Xcode 10 • Swift 4.2

 extension ClosedRange where Bound == Unicode.Scalar { static let asciiPrintable: ClosedRange = " "..."~" var range: ClosedRange<UInt32> { return lowerBound.value...upperBound.value } var scalars: [Unicode.Scalar] { return range.compactMap(Unicode.Scalar.init) } var characters: [Character] { return scalars.map(Character.init) } var string: String { return String(scalars) } } 

 extension String { init<S: Sequence>(_ sequence: S) where S.Element == Unicode.Scalar { self.init(UnicodeScalarView(sequence)) } } 

 let characters = ("a"..."z").characters // "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] let string = ("a"..."z").string // "abcdefghijklmnopqrstuvwxyz" 

 let range = ClosedRange.asciiPrintable // {lowerBound " ", upperBound "~"} 32...126 let characters = range.characters // [" ", "!", """, "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "'", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~"] let string = range.string // " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~" 
+6
source share

If you need an array of a known set:

 let str = "abcdefghijklmnopqrstuvwxyz" let characterArray = Array(str) println(characterArray) //[a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z] 
+4
source share

In Swift 5, you can use the following Playground code example to get an array of characters from a series of Unicode scalars:

 // 1. let unicodeScalarRange: ClosedRange<Unicode.Scalar> = "A" ... "Z" // 2. let unicodeScalarValueRange: ClosedRange<UInt32> = unicodeScalarRange.lowerBound.value ... unicodeScalarRange.upperBound.value // 3. let unicodeScalarArray: [Unicode.Scalar] = unicodeScalarValueRange.compactMap(Unicode.Scalar.init) // 4. let characterArray: [Character] = unicodeScalarArray.map(Character.init) print(characterArray) /* prints: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] */ 
  1. Create a range of Unicode scalars that correspond to the code points for the uppercase Latin alphabet Unicode block.
  2. Since this first range is not strideable (you cannot iterate over it), convert it to a Unicode range of scalar number representations using the Unicode.Scalar value property .
  3. Iterate over your range of Unicode scalar numeric representations to create an array of Unicode scalars.
  4. Iterate over your Unicode scalar array to create an array of characters.

Alternatively, you can use one of the following code examples if you need to start with the Character range or the String range:

 let unicodeScalarRange: ClosedRange<Character> = "A" ... "Z" let unicodeScalarValueRange = unicodeScalarRange.lowerBound.unicodeScalars[unicodeScalarRange.lowerBound.unicodeScalars.startIndex].value ... unicodeScalarRange.upperBound.unicodeScalars[unicodeScalarRange.lowerBound.unicodeScalars.startIndex].value let unicodeScalarArray = unicodeScalarValueRange.compactMap(Unicode.Scalar.init) let characterArray = unicodeScalarArray.map(Character.init) print(characterArray) /* prints: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] */ 
 let unicodeScalarRange: ClosedRange<String> = "A" ... "Z" let unicodeScalarValueRange = unicodeScalarRange.lowerBound.unicodeScalars[unicodeScalarRange.lowerBound.unicodeScalars.startIndex].value ... unicodeScalarRange.upperBound.unicodeScalars[unicodeScalarRange.lowerBound.unicodeScalars.startIndex].value let unicodeScalarArray = unicodeScalarValueRange.compactMap(Unicode.Scalar.init) let characterArray = unicodeScalarArray.map(Character.init) print(characterArray) /* prints: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] */ 
+2
source share

More details

  • Xcode Version 10.3 (10G8), Swift 5

Solution 1

 // MAKR: - ClosedRange extensions extension ClosedRange where Bound == Unicode.Scalar { var representationRange: ClosedRange<UInt32> { return lowerBound.value...upperBound.value } var scalars: [Bound] { return representationRange.compactMap(Bound.init) } } extension ClosedRange where Bound == Character { var scalars: [Unicode.Scalar]? { guard lowerBound.unicodeScalars.count == 1, upperBound.unicodeScalars.count == 1 else { return nil } return (lowerBound.unicodeScalars.first! ... upperBound.unicodeScalars.first!).scalars } var all: [Bound]? { return scalars?.map(Character.init) } } extension ClosedRange where Bound == String { var scalars: [Unicode.Scalar]? { guard lowerBound.unicodeScalars.count == 1, upperBound.unicodeScalars.count == 1, let first = lowerBound.first, let last = upperBound.first else { return nil } return (first...last).scalars } var all: [Bound]? { return scalars?.map(String.init) } } // MAKR: - Array extensions extension Array where Element == Character { init?(_ range: ClosedRange<Element>) { guard let array = range.all else { return nil } self = array } } extension Array where Element == String { init?(_ range: ClosedRange<Element>) { guard let array = range.all else { return nil } self = array } } extension Array where Element == Unicode.Scalar { init(_ range: ClosedRange<Element>) { self = range.scalars } } 

Usage 1

 func test(value: Any) { print("-- \(type(of: value)) : \(value)") } print("====================") test(value: ("a"..."z").scalars ?? []) test(value: ("a"..."z").all ?? []) test(value: ("aa"..."z").all ?? []) test(value: ("a"..."zz").all ?? []) print("====================") test(value: (Character("a")...Character("z")).scalars ?? []) test(value: (Character("a")...Character("z")).all ?? []) print("====================") test(value: (Unicode.Scalar("a")...Unicode.Scalar("z")).scalars) print("====================") test(value: [Unicode.Scalar]("a"..."z")) test(value: [Character]("a"..."z") ?? []) test(value: [String]("a"..."z") ?? []) test(value: [String]("aa"..."z") ?? []) test(value: [String]("a"..."zz") ?? []) 

Usage Log 1

 ==================== -- Array<Scalar> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Array<String> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Array<String> : [] -- Array<String> : [] ==================== -- Array<Scalar> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Array<Character> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] ==================== -- Array<Scalar> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] ==================== -- Array<Scalar> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Array<Character> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Array<String> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Array<String> : [] -- Array<String> : [] 

Decision 2

 extension Unicode.Scalar: Strideable { public typealias Stride = Int public func distance(to other: Unicode.Scalar) -> Stride { return abs(Int(value) - Int(other.value)) } public func advanced(by n: Stride) -> Unicode.Scalar { return Unicode.Scalar(value + UInt32(n)) ?? self } } extension Character: Strideable { public typealias Stride = Int public func distance(to other: Character) -> Stride { guard unicodeScalars.count == 1, other.unicodeScalars.count == 1 else { return 0 } return unicodeScalars.first!.distance(to: other.unicodeScalars.first!) } public func advanced(by n: Stride) -> Character { guard unicodeScalars.count == 1 else { return self } return Character(unicodeScalars.first!.advanced(by: n)) } } extension Array where Element == String { init?(_ range: ClosedRange<Element>) { guard range.lowerBound.unicodeScalars.count == 1, range.upperBound.unicodeScalars.count == 1, let first = range.lowerBound.unicodeScalars.first, let last = range.upperBound.unicodeScalars.first else { return nil } self = [Unicode.Scalar](first...last).map(String.init) } } 

Usage 2

 func test(value: Any) { print("-- \(type(of: value)) : \(value)") } test(value: [Unicode.Scalar]("a"..."z")) test(value: [Character]("a"..."z")) test(value: [String]("a"..."z")) test(value: Array("a"..."z")) test(value: Array(Character("a")...Character("z"))) test(value: Array(Unicode.Scalar("a")...Unicode.Scalar("z"))) 

Usage Log 2

 -- Array<Scalar> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Array<Character> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Optional<Array<String>> : Optional(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]) -- Optional<Array<String>> : Optional(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]) -- Array<Character> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] -- Array<Scalar> : ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] 
+1
source share

Solution for:

 // trying to do something like this (pseudo code): // let letters:[Character] = map(0..<26) { i in 'a' + i } 

with Swift 4.2 / 5.0:

 extension Character: Strideable { public typealias Stride = Int // https://stackoverflow.com/questions/39982335/creating-a-countableclosedrangecharacter public func distance(to other: Character) -> Character.Stride { let stride = Int(String(self).unicodeScalars.first!.value) - Int(String(other).unicodeScalars.first!.value) return abs(stride) } public func advanced(by n: Character.Stride) -> Character { return Character(UnicodeScalar(String(self).unicodeScalars.first!.value + UInt32(n))!) } } extension ClosedRange where Element == Character { var characters: [Character] { return Array(self) } } 

outputs:

 let letters: [Character] = ("A"..."Z").characters print(letters) // ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] 
0
source share

(11 ... 36) .map {String ($ 0 - 1, base: $ 0)}

-one
source share

You can simply use let alphabets: [UnicodeScalar] = Array("A"..."Z")

-4
source share

All Articles