I need something that converts a particular key/value within a sequence of maps into a single map. this->that
will do nicely.
(defn this->that [this that vs]
"Build a map out of sequence vs; taking `this` as the key and `that` as the value from each"
(reduce
(fn [acc v] (assoc acc (this v) (that v)))
{}
vs))
;; -> {:key-1 :value-1, :key-2 :value-2}
Let's create some data for this example.
(def data
[{:id 1 :email "mouse@hanna-barbera.com" :name "Bullwinkle J. Mouse"}
{:id 2 :email "squirrel@hanna-barbera.com" :name "Rocky the Flying Squirrel"}
{:id 3 :email "boris@hanna-barbera.com" :name "Boris Badenov"}
{:id 4 :email "ffetale@hanna-barbera.com" :name "Natasha Fatale"}
{:id 5 :email "leader@hanna-barbera.com" :name "Fearless Leader"}])
With this->that
and our data
, we can now create a map of :id
to :email
.
(defn id->email [vs]
(this->that :id :email vs))
(id->email data)
Or :id
to :name
.
(defn id->name [vs]
(this->that :id :name vs))
(id->name data)
Within this->that
the arguments this
and that
are being called. This must mean that keywords (:id
, :email
, and :name
in our case) are callable as functions! this->that
actually takes two functions as the this
and that
arguments. this->that
can take a sequence of any type in vs
, provided that you can write functions to pull values from every element in vs
.
Let's illustrate the equivalency of keywords and functions below.
(= (this->that :id :name data)
(this->that #(:id %) #(:name %) data))