Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard func that takes a dict and a list of keys and returns the list of corresponding vals?

Tags:

clojure

I'm looking for something similar to select-keys:

(desired-fn {:a 1, :b 2, :c 3, :d 4} [:a :d])
;= [1 4]

;; N.B. the order of the keys in the argument seq is preserved
(= (desired-fn (array-map :a 1, :b 2, :c 3, :d 4)
               [:b :c])
   (desired-fn (array-map :d 4, :c 3, :a 1, :b 2)
               [:b :c]))
;= true

It's not particularly hard to implement, though I haven't tried to come up with a good name yet:

(defn select-values-corresponding-to-keys [m ks]
  (for [k ks]
    (get m k)))

Am I ignorant of a standard function that meets precisely this need? If not, do other languages —e.g., Python, Ruby, Haskell— have a name for this function?

like image 828
Josh Tilles Avatar asked May 28 '13 22:05

Josh Tilles


2 Answers

Maps are functions which operate on their keys:

({:a 1, :b 2} :a)
;=> 1

(map {:a 1, :b 2, :c 3, :d 4} [:a :d])
;=> (1 4)

(= (map (array-map :a 1, :b 2, :c 3, :d 4)
           [:b :c])
   (map (array-map :d 4, :c 3, :a 1, :b 2)
           [:b :c]))
;=> true

If you want the result as a vector, just use vec or into [] ..., or replace map with mapv.

like image 109
JohnJ Avatar answered Nov 03 '22 10:11

JohnJ


Keywords are themselves functions (they implement IFn) and they can look themselves into a map and return the value so one option would be to use juxt:

(def keys-to-vals (juxt :b :c))
(= (keys-to-vals {:a 1, :b 2, :c 3, :d 4})
   (keys-to-vals {:d 4, :c 3, :a 1, :b 2}))

So basically your desired fn now becomes:

(defn select-vals [map keys] ((apply juxt keys) map))
like image 29
Ankur Avatar answered Nov 03 '22 09:11

Ankur