Rosie
Rosie

Reputation: 3

String into array in Swift 3

I am trying to transform a string of the following format into an array (...of arrays, of floats!) in Swift 3:

"[173.0, 180.5],[173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"

so that the output would be an array in this format:

[[173.0, 180.5, 173.0, 180.0],[174.0, 180.5, 174.0, 183.0]]

I am really new to Swift and struggling to find any String functions that will allow me to convert the data in this way. Any pointers on how I can do it would be awesome - thanks!

Upvotes: 0

Views: 550

Answers (3)

Code Different
Code Different

Reputation: 93191

Swift 4

You can use Decodable:

let str = "[173.0, 180.5],[173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"
let json = "[\(str)]".data(using: .utf8)!

let numbers = try JSONDecoder().decode([[Double]].self, from: json).flatMap { $0 }
let result = stride(from: 0, to: numbers.count, by: 4).map { startIndex -> [Double] in
    let endIndex = min(startIndex + 4, numbers.count)
    return Array(numbers[startIndex..<endIndex])
}

Swift 3

One option is to use the old-school NSScanner to extract the numbers from the string to a flat array, then build a 2 dimensional array off that:

let str = "[173.0, 180.5],[173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"
let scanner = Scanner(string: str)
scanner.charactersToBeSkipped = CharacterSet(charactersIn: "[], ")

// Build the flat array
var numbers = [Double]()
while !scanner.isAtEnd {
    var d = 0.0
    if scanner.scanDouble(&d) {
        numbers.append(d)
    }
}

// Now the 2 dimensional array
let result = stride(from: 0, to: numbers.count, by: 4).map { startIndex -> [Double] in
    let endIndex = min(startIndex + 4, numbers.count)
    return Array(numbers[startIndex..<endIndex])
}

Upvotes: 0

Rob
Rob

Reputation: 438232

As Martin said, you first want to first convert this from a string to an array. In Swift 3:

let string = "[173.0, 180.5],[173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"
let jsonString = "[" + string + "]"

guard let data = jsonString.data(using: .utf8),
    let json = try? JSONSerialization.jsonObject(with: data),
    let numberPairs = json as? [[Double]] else {
        fatalError("string was not well-formed: \(string)")
}

You then want to combine these pairs of numbers together:

var combinedNumbers = [[Double]]()
var current: [Double]?
for numberPair in numberPairs {
    if current != nil {
        combinedNumbers.append(current! + numberPair)
        current = nil
    } else {
        current = numberPair
    }
}

// use `combinedNumbers` here

Clearly, you should use better variable names (perhaps something that suggests what these sets of numbers are), but hopefully this illustrates the idea.

Upvotes: 1

Jonathan H.
Jonathan H.

Reputation: 949

One option to convert the data types would be to develop a simple algorithm that will iterate through the string and analyze elements and square bracket delimiters, returning the appropriate conversion.

Below is the skeleton of what the fundamental components of such a function could look like. Included are some basic aspects of the conversion from string to array.

var str = "[173.0, 180.5], [173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"

// Cast returns array ["[","1","7","3",".","0",",".......]
let array = Array(str.characters)

// Iterate through array
for char in array {

    if char == "[" || char == "]" {
        // Deal with array delimiters appropriately
    }

    ...

}

It might help to check out this similar problem.

NOTE: As Martin R mentioned, JSON interpretation may be a good method as well.

Upvotes: 0

Related Questions