New to clojure with a java background. I have the following table and need to transform the table to a hash-map that maps products to the city that has the highest sale. For example, the output should look like:
{"Pencil": "Toronto"
"Bread": "Ottawa"}
(def table [
{:product "Pencil"
:city "Toronto"
:year "2010"
:sales "2653.00"}
{:product "Pencil"
:city "Oshawa"
:year "2010"
:sales "525.00"}
{:product "Bread"
:city "Toronto"
:year "2010"
:sales "136,264.00"}
{:product "Bread"
:city "Oshawa"
:year "nil"
:sales "242,634.00"}
{:product "Bread"
:city "Ottawa"
:year "2011"
:sales "426,164.00"}])
This is what I have so far:
(reduce (fn [product-cities {:keys [product sales]}]
(update-in product-cities [product] (fnil conj []) sales))
{}
table)
This produces the outcome:
{"Bread"
["136,264.00"
"242,634.00"
"426,164.00"],
"Pencil" ["2653.00" "525.00"]}
How can i compare the sales of each city and and only keep the name of the city with the highest sales? Having a really tough time with this. Thanks
there is a handy function max-key
in clojure.core, that is perfectly suitable for this case:
(defn process [table]
(let [parseDouble #(Double/parseDouble (clojure.string/replace % #"," ""))]
(->> table
(group-by :product)
(map (comp (juxt :product :city)
(partial apply max-key (comp parseDouble :sales))
val))
(into {}))))
user> (process table)
;;=> {"Pencil" "Toronto", "Bread" "Ottawa"}
the key is that (partial apply max-key (comp parseDouble :sales))
part looks for the record in a group, having maximum parsed sales value.