octopusgrabbus
octopusgrabbus

Reputation: 10685

Trying to Determine Why nth Fails With Specific Input

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.

Upvotes: 0

Views: 133

Answers (1)

Justin Kramer
Justin Kramer

Reputation: 4003

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")

Upvotes: 1

Related Questions