Swift 4: Code to check if a CSV string has an Int followed by a Float

What code in Swift 4 can be used to determine whether a line in a CSV file has an Int followed by a Float? The format of a well formed file is shown below.


1818,0.052

1822,0.042

1826,0.036


The following types of arrangements could occur:

aaa,0.013

\n

32.3

asdfasdf


Thank you.

Accepted Answer

You can call: components(separatedBy:)


let toSplit = "aaa,0.013"
let splitted = toSplit.components(separatedBy: ",")

That gives you an array

["aaa", "0.013"]


let toSplit = "1818,0.052"
let splitted = toSplit.components(separatedBy: ",")

gives

["1818", "0.052"]


then for you test:

func isWellFormed(splitted: [String]) -> Bool {

     if splitted.count != 2 { return false  } 

     // Now, we know there 2 items, need to check if those strings are of expected type
     let first = splitted[0]
     let second = splitted[1]
     // for the first,
      let test1 = Int(first)      // this gives nil if not an Int
      if test1 == nil { return false }

     // for second:
     let test2 = Double(second) // this give nil if not a double ; but would be ok also for an Int
      if test2 == nil { return false }
      let test3 = Int(second)      // this gives nil if not an Int
      if test3 != nil { return false }

     return true
}


call

let wellFormed = isWellFormed(splitted: splitted)

Here’s how I’d do this:

func parse(line: String) -> (Int, Double)? {
    let parts = line.split(separator: ",", omittingEmptySubsequences: false)
    guard parts.count == 2 else {
        return nil
    }
    guard let i = Int(parts[0]), let d = Double(parts[1]) else {
        return nil
    }
    return (i, d)
}

print(parse(line: "aaa,0.013"))     // -> nil
print(parse(line: ""))              // -> nil
print(parse(line: "32.3"))          // -> nil
print(parse(line: "asdfasdf"))      // -> nil
print(parse(line: "1818,0.052"))    // -> Optional((1818, 0.051999999999999998))

That not only checks the line but also gives you back the results you want.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Quinn,


that will not work in all cases


parse (line: "128,150")


returns optional((128, 150.0), which is not the expected result

Because Double(of an Int) does not fail.


Hence the additional test:

let test3 = Int(second) // this gives nil if not an Int, which is what is expected


But surprisingly:

parse (line: "128, 150") // with a space before 150

returns nil


I don't understand why this difference

I want to thank everybody for their posts. I created a function to test each row before parsing it. In my case, I have rows of CSV, each with an Int followed by a Float. This fuction will not work in all cases, but it was successful in catching the errors I was experiencing in my situation. The function uses the.ASCII table found here http://www.asciitable.com.


I think it could be improved by only allowign the characters that should appear in a valid CSV: "0123456789,-.". But this is fine for my purposes unless I can find an effective working improvement. Thanks again everybody.


func isStringOK(to st: String) -> Bool {

// Includes all letters and some symbols

// See http://www.asciitable.com ASCII Table and Description

print("ENTERING isStringOK - checking for excluded characters...")

var isStringOK = true

var numChar = 0

for ch in st {

if (ch >= ":") {

print(ch)

isStringOK = false

numChar = numChar + 1

}

if (ch < " ") {

print(ch)

isStringOK = false

numChar = numChar + 1

}

if (ch == "/") {

print(ch)

isStringOK = false

numChar = numChar + 1

}

if (ch <= "+") && (ch >= "!") {

print(ch)

isStringOK = false

numChar = numChar + 1

}

if (ch == " ") {print("\n")}

}

print("ch = Number of excluded characters: \(numChar)")

/

print(st)

numChar = st.characters.count

if numChar < 3 {isStringOK = false}

/

let commas = st.characters.filter { $0 == "," }.count

if(commas != 1) {isStringOK = false}

return isStringOK

}

Thank you.

Swift 4: Code to check if a CSV string has an Int followed by a Float
 
 
Q