An idiomatic way to select a card in a vector using a key

Suppose I have this vector of mappings:

[{:title "Title1" :id 18347125}
 {:title "Title2" :id 18347123}
 {:title "Title3" :id 18341121}]

      

And I want to select a card with: id 18347125, how would I do that?

I tried

(for [map maps
      :when (= (:id map) id)]
    map)

      

This seems a little ugly and returns a sequence of length one and I only want to return the map.

+3


source to share


4 answers


I'm not sure if this is the easiest way to write this, but I think it is clearer about your intentions:



(->> maps
     (filter #(= (:id %) id))
     first)

      

+1


source


IMHO, there are several ways to solve your problem, and the definitely idiomatic way is in the realm of taste. It's my decision, I just translated "to select the card, :id

which 1834715

" in Clojure.

user> (def xs [{:title "Title1" :id 18347125}
               {:title "Title2" :id 18347123}
               {:title "Title3" :id 18341121}])
#'user/xs

user> (filter (comp #{18347125} :id) xs)
({:title "Title1", :id 18347125})

      



A keyword :id

is a function that itself searches the collection passed to it. Set is #{18347125}

also a function that checks if a value is equal to 18347125

. Using Clojure, defined as a predicate function, allows for a concise idiom.

+5


source


This is not exactly what you asked for, but it might be useful, nevertheless:

user=> (group-by :id [{:title "Title1" :id 18347125}
                      {:title "Title2" :id 18347123}
                      {:title "Title3" :id 18341121}])
{18347125 [{:title "Title1" :id 18347125}]
 18347123 [{:title "Title2" :id 18347123}]
 18341121 [{:title "Title3" :id 18341121}]}

      

Now you can just look up the map by id. Read more about group-on at clojuredocs , it's a very useful feature.

Note that it puts maps inside vectors. This is because group-by is designed to handle grouping (i.e. Multiple items with the same key):

user=> (group-by :id [{:title "Title1" :id 123}
                      {:title "Title2" :id 123}
                      {:title "Title3" :id 18341121}])
{123 [{:title "Title1" :id 123} {:title "Title2" :id 123}]
 18341121 [{:title "Title3" :id 18341121}]}

      

+1


source


If you need to query not only once, but multiple times for cards with specific IDs, I would suggest making your datatypes appropriate for your use, i.e. change vector to map:

(def maps-by-id (zipmap (map :id maps) maps))

      

So now your IDs are the keys on this new map of maps:

user=> (maps-by-id 18347125)
{:title "Title1", :id 18347125}

      

0


source







All Articles