0
votes

Given the following vector parsed by clojure-csv

["123/45678" "RET" "xxx-yy-zzzz" "TOAST" "FRENCH" "SOME KIND OF COVERAGE - INSURED" "0" "12345678" "102020"]

nth is causing an exception in the following function.

(defn reduce-csv-row
    "Accepts a csv-row and a list of columns to extract, and
     reduces the csv-row to the selected list."

    [csv-row col-nums]

    (reduce
        (fn [out-csv-row col-num]

            ;Without testing for empty, a 
            ;java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number
            ;would occur if the file contained a blank line.

            (let [temp-val
                (try
                    (nth csv-row col-num nil)
                    (catch Exception e (do 
                                        (println csv-row, " ", col-num)
                                        (.getMessage e))))])

                    (conj out-csv-row (nth csv-row col-num nil)))
        []
        col-nums))

The try .. catch will eventually go away, I just wanted the least amount of debug printout.

For the life of me, I cannot figure out why nth throws an exception. It does not at the repl. And data in another .csv file with quoted fields, very similar to the sample row I've included does not fail. I think this is due to something subtle that I cannot see.

I would appreciate any help or ways to go about debugging this problem.

Thank you.

Edit:

Using the first method above, I get an error indicating that a Java string can't be converted to an integer.

The mask vector is converted to integer using this function:

(defn cvt-mask-numeric
    "Converts a vector mask to numbers. It was read from a file, so it's a series of strings.
    Build in some protection in case we get a non-string. Don't want stuff to blow up."

    [csv-mask]
    (map #(utl/parse-int %) csv-mask))

Using the following method

(defn reduce-csv-row
    "Accepts a csv-row and a list of columns to extract, and
     reduces the csv-row to the selected list."

    [csv-row col-nums]

    (try
        (map #(nth csv-row %) col-nums)
        (catch Exception e (.getMessage e) (println csv-row, " ", col-nums))))

I get a java.lang.IndexOutOfBoundsException

The problem is I forgot to pass the second mask through the converter:

(let [bene-csv-data (bcsv/strip-csv-header (fetch-csv-data (:ifn1 opts)))
      bene-csv-mask (bcsv/cvt-mask-numeric (first (fetch-csv-data (:ifm1 opts))))
      gic-csv-data  (bcsv/strip-csv-header (fetch-csv-data (:ifn2 opts)))
      gic-csv-mask  (first (fetch-csv-data (:ifm2 opts)))

Thanks for the comments, because they helped me go back and look.

1
It seems that col-nums has some values which are string and not numbersAnkur
The first exception is a Java string to integer. I'll go off and get the exact one. The mask input looks like this and is parsed also by clojure-csv, but you may have hit the nail on the head. I'll get back to you. They look like numbers, but might be strings. Here is the value of col-nums: 2,3,4,5octopusgrabbus
The exception is java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number and is in the original post. I also pass both masks through an integer converter which I'll add to the original post.octopusgrabbus
You answered the question Ankur. Why don't you post an official answer?octopusgrabbus

1 Answers

1
votes

It's hard to know what's causing your code to fail without seeing the input you're passing it, but reduce-csv-row could probably be replaced with a simple call to map:

(def v ["123/45678" "RET" "xxx-yy-zzzz" "TOAST" "FRENCH" "SOME KIND OF COVERAGE - INSURED" "0" "12345678" "102020"])

;; extract values from a vector at indexes 0, 2, and 4
(map v [0 2 4])
=> ("123/45678" "xxx-yy-zzzz" "FRENCH")