2

How can I convert this:

let numbersStringArray = "[-1, -2, -3, -4, -5, 6, -7, -8, -9, -10]"

into an array of integers:

[-1, -2, -3, -4, -5, 6, -7, -8, -9, -10]

I know one way to implement thin swift is to do like this:

let formatter = NSNumberFormatter()
var numbers = numbersStringArray.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "[]")).componentsSeparatedByString(",").map { formatter.numberFromString($0)?.integerValue
 }

But I need more shorter coded solution please.

7
  • Why? If what you have works... Commented May 23, 2016 at 12:41
  • Is it always going to be JSON formatted? Commented May 23, 2016 at 12:41
  • 1
    Is numbersStringArray an array of Strings or a string formatted to look like an array? Commented May 23, 2016 at 12:46
  • a string that looks like an array Commented May 23, 2016 at 12:47
  • and will it always contain correctly formatted integers? Commented May 23, 2016 at 12:48

3 Answers 3

3

Since you're telling us that your String is always formatted as JSON, you can use NSJSONSerialization to decode it to an array:

if let data = numbersStringArray.dataUsingEncoding(NSUTF8StringEncoding),
        json = try? NSJSONSerialization.JSONObjectWithData(data, options: []),
        array = json as? [Int] {
    print(array)
}

This is not shorter than your example but I think it's the right way to do this.

Sign up to request clarification or add additional context in comments.

Comments

2

A bit shorter is

let numbers = numbersStringArray.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "[]"))
                                .componentsSeparatedByString(", ")
                                .flatMap { Int($0) }

In this case

numbersStringArray.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "[]"))

can be also replaced with

numbersStringArray.substringWithRange(numbersStringArray.startIndex.successor()..<numbersStringArray.endIndex.predecessor())

but this makes the code longer ;-)

5 Comments

thank you, but I would like something shorter if possible. Something like Array(numbersStringArray)
You can use flatMap to filter out non-integer strings
Thanks for the improvement, I updated the answer. @IamMashed Go for the most efficient rather than the shortest code.
@Wain So you are saying my wish is not possible?
@IamMashed You could always write an Array extension with a custom initialiser to do this. I have written an answer demonstrating how you could do this.
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.