Ebel Ofori
Ebel Ofori

Reputation: 13

is possible to create a map with 2 keys and a vector of values in Clojure?

I am trying to create a program that reads in a table of temperatures from a csv file and would like to access a a collection of temperatures based on the year and day.

the first column stands for the year the tempratures have been recorded. the second column stands for a specific day during each month . the rest of the column represent the temperatures each month.

For example, 2021 - 23 - 119 = 23rd June 2021 has a temperature of 119

Year   Day      Months from January to December

2018     18  | 45   54  -11  170   99  166  173  177  175   93   74   69

2021     23  | 13   87   75   85   85  119  190  172  156  104   39   53 


2020     23  | 63   86   62  128  131  187  163  162  138  104   60   70 

So far I have managed to load the data from a CSV File with clojure.data.csv. this returns a sequence of vectors into the program

  (defn Load_csv_file  [filepath]
 (try
   (with-open [reader (io/reader filepath)]
     (.skip reader 1)
     ( let [data (csv/read-csv reader)]
       (println  data) )
     )
   (catch Exception ex (println (str "LOL Exception: " (.toString ex))))
   ))

I am currently trying to figure out how to implement this but my reasoning was to create three keys in a map which will take in the year, day and vector of temperatures, to then filter for a specific value.

Any advice on how i can implement this functionality.

Thanks!

Upvotes: 0

Views: 148

Answers (2)

J Blaz
J Blaz

Reputation: 783

I would create a map of data that looked something like this

{2020 {23 {:months [63 86 62 128 131 187 163 162 138 104 60 70]}}}

This way you can get the data out in a fairly easy way (get-in data [2020 23 :months]

So something like this

(->> (Load_csv_file "file.csv")
     (reduce (fn [acc [year day & months]] (assoc-in acc [year day] months)) {}))

This will result in the data structure I mentioned now you just need to figure out the location of the data you want

Upvotes: 0

leetwinski
leetwinski

Reputation: 17859

i would go with something like this:

(require '[clojure.java.io :refer [reader]]
         '[clojure.string :refer [split blank?]]
         '[clojure.edn :as edn])

(with-open [r (reader "data.txt")]
  (doall (for [ln (rest (line-seq r))
               :when (not (blank? ln))
               :let [[y d & ms] (mapv edn/read-string (split ln #"\s+\|?\s+"))]]
           {:year y :day d :months (vec ms)})))

;;({:year 2018,
;;  :day 18,
;;  :months [45 54 -11 170 99 166 173 177 175 93 74 69]}
;; {:year 2021,
;;  :day 23,
;;  :months [13 87 75 85 85 119 190 172 156 104 39 53]}
;; {:year 2020,
;;  :day 23,
;;  :months [63 86 62 128 131 187 163 162 138 104 60 70]})

by the way, i'm not sure csv format allows different separators (as you have in your example.. anyway this one would work for that)

Upvotes: 1

Related Questions