Reputation: 119
I'm trying some sample code in Swift and combined two principles: Array.map and Extension. Unfortunately, I get the error code "'T' is not identical to 'Int'" (line 3). So my question should probably be: how can I transform a T array into a Int array?
Thanks in advance for your answers!
Cheers.
extension Array {
func translateToDigitalNames()-> [String] {
var numbers : [Int] = self
let digitNames =
[0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"]
var strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
return strings
}
}
let x = [26, 158, 610]
x.translateToDigitalNames()
Upvotes: 1
Views: 195
Reputation: 72750
I would split the problem into 3 distinct subproblems.
The first is translating an integer into a string representation, implemented as a static method:
private static func translateToDigitalName(var number: Int) -> String {
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
The reasons for making it a separate function are: separation of concerns, reusability, readability.
Next, we can implement a static method that, given an array of integers, returns an array of their respective string representations:
private static func translateToDigitalNames(numbers: [Int])-> [String] {
return numbers.map { self.translateToDigitalName($0) }
}
Last, the actual array extension. The approach I'm using is to filter the array by excluding elements not castable to Int:
func translateToDigitalNames()-> [String] {
let numbers: [Int] = self.filter { $0 is Int }.map { $0 as Int }
return Array.translateToDigitalNames(numbers)
}
If you want the translation to fail if at least one array element is not an Int, just add an explicit check and return nil in that case:
func translateToDigitalNames()-> [String]? {
let numbers: [Int] = self.filter { $0 is Int }.map { $0 as Int }
if numbers.count != self.count {
return nil
}
return Array.translateToDigitalNames(numbers)
}
Note that the return type is now an optional.
Last thing, rather than creating the digitNames
array at every function invocation, I've moved it as a private global and immutable variable
The full code is available on this gist
Side note: the translateToDigitalNames
and translateToDigitalName
can be moved outside of the array extension, as global and public functions - and that's actually what I'd recommend in case you need to reuse them in the future.
Upvotes: 1
Reputation: 36295
It's not a good idea to write such kind of extension since it applies only to [Int]
arrays. What should happen if you would do
["some", "strings"].translateToDigitalNames()
Instead use a function like this:
func translateToDigitalNames(numbers:[Int])-> [String] {
let digitNames =
[0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"]
var strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
return strings
}
let x = [26, 158, 610]
translateToDigitalNames(x)
So the compiler ensures you always supply a [Int]
Upvotes: 1
Reputation: 12015
You can create the numbers
array with a map function as well, like:
var numbers = map { $0 as Int }
Upvotes: 1