0

This is similar to Clojure get map key by value

However, there is one difference. How would you do the same thing if hm is like

{1 ["bar" "choco"]} 

The idea being to get 1 (the key) where the first element if the value list is "bar"? Please feel free to close/merge this question if some other question answers it.

I tried something like this, but it doesn't work.

(def hm {:foo ["bar", "choco"]}) (keep #(when (= ((nth val 0) %) "bar") (key %)) hm) 

3 Answers 3

6

You can filter the map and return the first element of the first item in the resulting sequence:

(ffirst (filter (fn [[k [v & _]]] (= "bar" v)) hm)) 

you can destructure the vector value to access the second and/or third elements e.g.

(ffirst (filter (fn [[k [f s t & _]]] (= "choco" s)) {:foo ["bar", "choco"]})) 

past the first few elements you will probably find nth more readable.

Sign up to request clarification or add additional context in comments.

3 Comments

That's a nice solution. Is it possible to check the second or the third element in the list in the same way? (I mean different position of v)
@smaug - Yes you can destructure multiple elements, see update.
'& _' is unnecessary in func args. (ffirst (filter (fn [[k [v]]] (= "bar" v)) hm)) is OK.
6

Another way to do it using some:

(some (fn [[k [v & _]]] (when (= "bar" v) k)) hm) 

Your example was pretty close to working, with some minor changes:

(keep #(when (= (nth (val %) 0) "bar") (key %)) hm) 

keep and some are similar, but some only returns one result.

1 Comment

You can omit unnecessary args. (some (fn [[k [v]]] (when (= "bar" v) k)) hm) is also OK.
3

in addition to all the above (correct) answers, you could also want to reindex your map to desired form, especially if the search operation is called quite frequently and the the initial map is rather big, this would allow you to decrease the search complexity from linear to constant:

(defn map-invert+ [kfn vfn data] (reduce (fn [acc entry] (assoc acc (kfn entry) (vfn entry))) {} data)) user> (def data {1 ["bar" "choco"] 2 ["some" "thing"]}) #'user/data user> (def inverted (map-invert+ (comp first val) key data)) #'user/inverted user> inverted ;;=> {"bar" 1, "some" 2} user> (inverted "bar") ;;=> 1 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.