Skip to content

Instantly share code, notes, and snippets.

@cgrand
Created May 29, 2012 10:15
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save cgrand/2823916 to your computer and use it in GitHub Desktop.
Save cgrand/2823916 to your computer and use it in GitHub Desktop.
Restricting nested maps to keys of interest
;; I could have used a closed dispatch (aka cond) but you may find this version more enjoyable
;; the spec format is the one provided by BG
(defprotocol Selector
(-select [s m]))
(defn select [m selectors-coll]
(reduce conj {} (map #(-select % m) selectors-coll)))
(extend-protocol Selector
clojure.lang.Keyword
(-select [k m]
(find m k))
clojure.lang.APersistentMap
(-select [sm m]
(into {}
(for [[k s] sm]
[k (select (get m k) s)]))))
;;;;;;;;;; example
(def my-map {:name "John Doe"
:email "john@doe.com"
:address {:house "42"
:street "Moon St."
:city "San Francisco"
:state "CA"
:zip 76509
:mobile "+188888888"}
:ssn "123456"
:spouse {:name "Jane Doe"
:ssn "654321"
:relation :wife
:address {:house "42"
:street "Moon St."
:city "Atlanta"
:state "GA"
:zip 76509
:mobile "+188888888"}}})
(select my-map
[:name :email {:address [:city :state]} {:spouse [:name {:address [:city :state]}]}])
; {:spouse {:address {:state "GA", :city "Atlanta"}, :name "Jane Doe"},
; :address {:state "CA", :city "San Francisco"},
; :email "john@doe.com",
; :name "John Doe"}
;; but maps can be merged and you'll get the same result
(select my-map
[:name :email {:address [:city :state]
:spouse [:name {:address [:city :state]}]}])
; {:spouse {:address {:state "GA", :city "Atlanta"}, :name "Jane Doe"},
; :address {:state "CA", :city "San Francisco"},
; :email "john@doe.com",
; :name "John Doe"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment