Astrid
Astrid

Reputation: 1936

Function argument as part of path to a file in Clojure

Suppose I have the same file name, placed in five different sub-folders. The file in question has the same name in all folders but otherwise has different values.

Suppose my file is called something like test.csv. My folder are A1,A2,A3,A4 and A5.

My data-read structure looks as so:

(defn my-data [folder]
  (loop [SUB-FOLDER (str 'folder)
         X []
         data (with-open [file (clojure.java.io/reader "./resources/SUB-FOLDER/test.csv")]
                (doall (csv/read-csv file)))]
    (def row (first data))
    (if (nil? row)
      [(lazy-seq X)]
      (recur (conj X (map #(Float/parseFloat %) row))
             (rest data)))))

I would call this function as so

(def Y (map vec (get (my-data A1) 0)))

Where I am trying to access the file test.csv in the sub-folder A1 which I am passing as an argument to my csv-read function.

Now obviously the above code does not work, but it provides an overview of what I am trying to achieve.

How could one make the minimal example work?

Thanks.

Upvotes: 2

Views: 117

Answers (1)

Diego Basch
Diego Basch

Reputation: 13069

Something like this should put your data from one folder into a sequence of sequences:

(defn read-data [folder]
  (let [data (csv/read-csv (slurp (str "./resources/" folder "/test.csv")))]
    (for [line data]
      (map #(Float/parseFloat %) line))))

Change map to mapv if you want to have vectors, and wrap the for with into [] if you want a vector of vectors. This assumes folder is a string. Because your files are very small you don't need to open them with a reader, it's easier to slurp them and then parse them.

A fe issues with your original code:

  • You're always trying to read a file called "./resources/SUB-FOLDER/test.csv" instead of replacing the name of your folder.
  • You don't want to use def inside a function. See let.
  • Calling lazy-seq on an already realized sequence doesn't do anything.
  • By calling doall on your reader you're forcing all your data into memory instead of reading it and processing it as you go (that's why I replaced it with slurp). If you're going to process it in a loop as you read it, you want the with-open outside the loop (and no doall).

Upvotes: 2

Related Questions