0

I have a string in Swift that looks like this:

["174580798","151240033","69753978","122754394","72373738","183135789","178841809","84104360","122823486","184553211","182415131","70707972"]

I need to convert it into an NSArray.

I've looked at other methods on SO but it is breaking each character into a separate array element, as opposed to breaking on the comma. See: Convert Swift string to array

I've tried to use the map() function, I've also tried various types of casting but nothing seems to come close.

Thanks in advance.

Community
  • 1
  • 1
Phil Hudson
  • 3,819
  • 8
  • 35
  • 59

4 Answers4

5

It's probably a JSON string so you can try this

let string = "[\"174580798\",\"151240033\",\"69753978\",\"122754394\",\"72373738\",\"183135789\",\"178841809\",\"84104360\",\"122823486\",\"184553211\",\"182415131\",\"70707972\"]"
let data = string.dataUsingEncoding(NSUTF8StringEncoding)!
let jsonArray = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(), error: nil) as! [String]

as the type [String] is distinct you can cast it forced

Swift 3+:

let data = Data(string.utf8)
let jsonArray = try! JSONSerialization.jsonObject(with: data) as! [String]
vadian
  • 274,689
  • 30
  • 353
  • 361
  • 2
    This really should be the accepted answer. The original string is obviously JSON and this is how you parse JSON. – Rob Aug 22 '15 at 12:26
2

The other two answers are working, although SwiftStudiers isn't the best regarding performance. vadian is right that your string most likely is JSON. Here I present another method which doesn't involve JSON parsing and one which is very fast:

import Foundation

let myString = "[\"174580798\",\"151240033\",\"69753978\",\"122754394\",\"72373738\",\"183135789\",\"178841809\",\"84104360\",\"122823486\",\"184553211\",\"182415131\",\"70707972\"]"

func toArray(var string: String) -> [String] {
    string.removeRange(string.startIndex ..< advance(string.startIndex, 2)) // Remove first 2 chars
    string.removeRange(advance(string.endIndex, -2) ..< string.endIndex)    // Remote last 2 chars
    return string.componentsSeparatedByString("\",\"")
}

toArray(myString)    // ["174580798", "151240033", "69753978", ...

You probably want the numbers though, you can do this in Swift 2.0:

toArray(myString).flatMap{ Int($0) }    // [174'580'798, 151'240'033, 69'753'978, ...

which returns an array of Ints

EDIT: For the ones loving immutability and functional programming, have this solution:

func toArray(string: String) -> [String] {
    return string[advance(string.startIndex, 2) ..< advance(string.endIndex, -2)]
        .componentsSeparatedByString("\",\"")
}

or this:

func toArray(string: String) -> [Int] {
    return string[advance(string.startIndex, 2) ..< advance(string.endIndex, -2)]
        .componentsSeparatedByString("\",\"")
        .flatMap{ Int($0) }
}
Kametrixom
  • 14,673
  • 7
  • 45
  • 62
1

Try this. I've just added my function which deletes any symbols from string except numbers. It helps to delete " and [] in your case

var myString = "[\"174580798\",\"151240033\",\"69753978\",\"122754394\",\"72373738\",\"183135789\",\"178841809\",\"84104360\",\"122823486\",\"184553211\",\"182415131\",\"70707972\"]"


        var s=myString.componentsSeparatedByString("\",\"")

        var someArray: [String] = []

        for i in s {
            someArray.append(deleteAllExceptNumbers(i))
        }
        println(someArray[0]);


func deleteAllExceptNumbers(str:String) -> String {
        var rez=""
        let digits = NSCharacterSet.decimalDigitCharacterSet()
        for tempChar in str.unicodeScalars {
            if digits.longCharacterIsMember(tempChar.value) {
                rez += tempChar.description
            }
        }
        return rez.stringByReplacingOccurrencesOfString("\u{22}", withString: "")
    }
SwiftStudier
  • 2,272
  • 5
  • 21
  • 43
  • But you did not come and post rich in perfomance answer, so you can leave your opinion to yourself – SwiftStudier Aug 22 '15 at 12:35
  • A few things to your code: Your function `deleteAllExceptNumbers` actually only does something to the first and last element; It creates an NSCharacterSet every time; it creates a new string every time even though 99% of the time the passed in string doesn't change at all, appending isn't cheap; why are you using `\u{22}` and not just `\"`?; your `someArray` has to allocate memory a lot of the time due to the `append`s; the original string gets walked through at least 3 times... Sorry to complain so much, but this just isn't very good code.. – Kametrixom Aug 22 '15 at 13:15
  • I'l take it into consideration, thanks. Think my nick will be explainful – SwiftStudier Aug 22 '15 at 13:18
1

Swift 1.2:

If as has been suggested you are wanting to return an array of Int you can get to that from myString with this single concise line:

var myArrayOfInt2 = myString.componentsSeparatedByString("\"").map{$0.toInt()}.filter{$0 != nil}.map{$0!}

In Swift 2 (Xcode 7.0 beta 5):

var myArrayOfInt = myString.componentsSeparatedByString("\"").map{Int($0)}.filter{$0 != nil}.map{$0!}

This works because the cast returns an optional which will be nil where the cast fails - e.g. with [, ] and ,. There seems therefore to be no need for other code to remove these characters.

EDIT: And as Kametrixom has commented below - this can be further simplified in Swift 2 using .flatMap as follows:

var myArrayOfInt = myString.componentsSeparatedByString("\"").flatMap{ Int($0) }

Also - and separately:

With reference to Vadian's excellent answer. In Swift 2 this will become:

// ...

do {
    let jsonArray = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! [String]
} catch {
    _ = error // or do something with the error
} 
simons
  • 2,374
  • 2
  • 18
  • 20