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