Reputation: 153
Given I have the following form:
(def data-points [[1483249740 "ONE"]
[1483249680 "TWO"]
[1483249620 "THREE"]
[1483249560 "FOUR"]])
How can I transform this data into this?
{:data [1483249740 1483249680 1483249620 1483249560]
:value ["ONE" "TWO" "THREE" "FOUR"]}
I would also like to know how to approach similar problems. What is your way to break this down and what functions do I need to know to transform any data.
I'm new to clojure and haven't found a satisfying solution for this.
Thank you
Upvotes: 2
Views: 366
Reputation: 17859
i would use this:
(zipmap [:data :value] (apply map vector data-points))
;;=> {:data [1483249740 1483249680 1483249620 1483249560],
;; :value ["ONE" "TWO" "THREE" "FOUR"]}
it uses a single pass over the data collections, but more concise than the reduction, yet shouldn't differ in terms of performance
the snippet (apply map vector data)
is quite an idiomatic way to transpose matrix in clojure (in your case it is what you need, since it turns columns into rows)
user> (apply map vector [[:a 1] [:b 2] [:c 3]])
;;=> ([:a :b :c] [1 2 3])
Upvotes: 8
Reputation: 1
Here's an obtusely functional way to do it
(->> data-points
(mapv (partial mapv vector))
(mapv (partial zipmap [:data :value]))
(reduce (partial merge-with into)))
As a function:
(def format-data-points
(comp (partial reduce (partial merge-with into))
(partial mapv (partial zipmap [:data :value]))
(partial mapv (partial mapv vector))))
(format-data-points data-points)
(I wouldn't recommend doing either of these actually, just presenting this for fun)
Upvotes: 0
Reputation: 691
Another representation which can be both efficient and easier to work with:
(def data-points-map
(into {} data-points))
Then you can do
(get data-points-map 1483249740)
to get "ONE". Otherwise you would need to
(aget (:value m) (.indexOf (:data m) 1483249740))
to achieve the same result.
Finally you can
{:data (keys data-points-map)
:value (values data-points-map)}
to get the "weird" representation in the original question.
Upvotes: 0
Reputation: 1306
I'd probably write this as a reduction. This approach only requires a single pass over 'data-points' which may be preferable.
(reduce
(fn [m [data value]]
(-> m
(update :data conj data)
(update :values conj value)))
{:data [] :values []}
data-points)
Upvotes: 1