0

Hi I am relatively new to swift. I am wanting build an array which contains an array of tuples from the string shown below. The count of tuples in each array is not always constant. The final data structure would be: [[(Double, Double)]]

String to be parsed: "((2363448.9 5860581.3, 2363438.0 5860577.9), (2363357.5 5860494.7, 2363303.2 5860502.0, 2363282.5 5860502.5), (2363357.5 5860494.7), (.........etc))"

I was wondering if anyone has any ideas about the best/most efficient way of doing this. I was thinking of iterating through the original string and setting flags by the character encountered. Then building strings for eastings and northings. But I'm not sure if this is the best way and seems overly complicated. Efficiency is a factor as the string can be quite large at times.

--UPDATE This is the code I have so far, which seems to work. Ideas on improvement or a better way are appreciated, as code is a bit messy. Thanks to everyone that has helped so far.

typealias Coordinate = (easting: Double, northing: Double)
typealias Coordinates = [[Coordinate]]

var array = Array<Array<Coordinate>>() //Array of array of tuples(Double)
var tupleArray = [Coordinate]() //Array of tuples(Double)
var tuple: (Double, Double)! = (0, 0)
var easting: Bool = false
var northing: Bool = false
var eastingString: String = ""
var northingString: String = ""
var openBracket = 0
let tempString = getSubstringFromIndex(wktGeometry , character: "G") //string to parse
for char in tempString.characters {
   if char == "(" {
       openBracket++
       if openBracket == 2 {
           easting = true
       }
   } else if char == ")" {
       openBracket--
       if openBracket == 1 {
           tuple.1 = Double(northingString)!
           tupleArray.append(tuple)
           array.append(tupleArray)
           tupleArray = [Coordinate]()
           eastingString = ""
           northingString = ""
       }
   } else if char == "," {
       if openBracket == 2 {
           tuple.1 = Double(northingString)!
           tupleArray.append(tuple)
           eastingString = ""
           northingString = ""
        }
   } else if char == " " {
       if easting == true {
           tuple.0 = Double(eastingString)!
           easting = false
           northing = true
       } else {
           northing = false
           easting = true
       }
    } else {
        if easting {
            eastingString += String(char)
        } else if northing {
            northingString += String(char)
        }
    } //end if
} //end for
print(array)
ozzyzig
  • 709
  • 8
  • 19

2 Answers2

1

The problem of your code is that you are trying to do everything at once. It will get much simpler if you split the task into small subtasks:

// will parse "2363448.9 5860581.3"
func parseCoordinate(coordinateString: String) -> (Double, Double) {
   // possible implementation:
   // 1. split string by space,
   // 2. assert there are two components
   // 3. parse them to Doubles and return them
}

// will parse "(2363448.9 5860581.3, 2363438.0 5860577.9)"
func parseCoordinates(coordinatesString: String) -> [(Double, Double)] {
   // possible implementation:
   // 1. remove last character "(" and end character ")"
   // 2. split the string by "," + remove spaces around results
   // 3. call parseCoordinate for every result (e.g. using "map" method)
}

// will parse your whole string
func parse(string: String) -> [[(Double, Double)]] {
   // possible implementation
   // 1. Use a smart regular expression to split by "," not inside "(" and ")" or just by string "), ("
   // 2. call parseCoordinates for every result (e.g. using "map" method)
} 

Most important things are:

  1. String splitting (see https://stackoverflow.com/a/25678505/669586)
  2. Array.map method
Community
  • 1
  • 1
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Ok great thanks I will lookup link and Array.map. Yes I agree the way I have written it is a bit messy and open to bugs if all cases are covered. – ozzyzig Oct 27 '15 at 20:24
-1

Essentially [[2363448.9 5860581.3, 2363438.0 5860577.9], [2363357.5 5860494.7, 2363303.2 5860502.0], [2363282.5 5860502.5, 2363357.5 5860494.7]] would use the JSON code that trojanfoe mentioned above. Outside of that, you could use a variable to store them and add them as you go using an append. It would certainly look cleaner, unless what you have is a constant.

Caleb Bach
  • 162
  • 11