I would like something shorter if possible. Something like Array(numbersStringArray)
You can do this by simply creating a convenience initialiser through an Array extension.
For example, decoding the string through JSON, as @Eric D suggests:
extension Array {
init?(jsonString: String) {
guard let array = (
try? JSONSerialization.jsonObject(with: Data(jsonString.utf8))
) as? [Element] else { return nil }
self.init(array)
}
}
let numbersStringArray = "[-1, -2, -3, -4, -5, 6, -7, -8, -9, -10]"
if let numberArray = [Int](jsonString: numbersStringArray) {
print(numberArray) // prints: [-1, -2, -3, -4, -5, 6, -7, -8, -9, -10]
}
Here we're returning an optional array to reflect the fact that the types could mismatch (the conditional downcasting to [Element] could fail), or the JSON deserialisation could fail.
Or spitting the string up manually as @vadian suggests:
protocol StringInitialisable {
init?(string: String)
}
extension Int : StringInitialisable {
init?(string: String) {
self.init(string)
}
}
extension Array where Element : StringInitialisable {
init(string: String) {
self.init(
string.trimmingCharacters(in: CharacterSet(charactersIn: "[]"))
.components(separatedBy: ", ")
.flatMap(Element.init)
)
}
}
let numbersStringArray = "[-1, -2, -3, -4, -5, 6, -7, -8, -9, -10]"
let numberArray = [Int](string: numbersStringArray)
print(numberArray) // prints: [-1, -2, -3, -4, -5, 6, -7, -8, -9, -10]
We're using a protocol here in order to explicitly specify the types that can be used for this initialiser – namely those that can be initialised with a string. This method won't return an optional if the type casting fails, it will simply exclude any type mismatches from the returned array. You could change it fairly easily to return an optional result if you want though.
Which method you use is completely up to you – if your string is always in a JSON format, then I would recommend going with the first option for increased flexibility.