Returns a map of the distinct values of ks in the xrel mapped to a set of the maps in xrel with the corresponding values of ks.
(use '[clojure.set :only (index)]) ;; Suppose you have a set of descriptions of the weights of animals: user=> (def weights #{ {:name 'betsy :weight 1000} {:name 'jake :weight 756} {:name 'shyq :weight 1000} }) ; You want the names of all the animals that weigh 1000. One way to do ; that uses `index`. First, you can group the set elements (the maps) so ; that those with the same weights are in the same group. user=> (def by-weight (index weights [:weight])) #'user/by-weight ; index returns a map. The keys are maps themselves, where {:weight 756} ; and {:weight 1000} are taken from the maps in the weights set. ; The values in the map returned by index are sets that contain map ; entries from the above weights set. user=> by-weight {{:weight 756} #{{:name jake, :weight 756}}, {:weight 1000} #{{:name shyq, :weight 1000} {:name betsy, :weight 1000}}} ; To better visualize the by-weight map that is returned by index, ; you can query it using get, using {:weight 756} as the key. This ; will return all the maps (animals) that contain a weight of 756. ; In this case, there is only one result, which is a set containing ; a single map. user=> (get by-weight {:weight 756}) #{{:name jake, :weight 756}} ; To see that there are two animals with a weight of 1000, you can ; query by-weight with the key {:weight 1000}. This returns a set ; containing two maps. user=> (get by-weight {:weight 1000}) #{{:name shyq, :weight 1000} {:name betsy :weight 1000}} ; You can verify by using count user=> (count (get by-weight {:weight 1000})) 2 ; To get the names of those two animals we can map a name-extracting function ; over the set of two maps. Since a keyword in a map is also a function that ; returns its corresponding value, we can just use `:name` as our function: user=> (map :name (get by-weight {:weight 1000})) (shyq betsy)
;; You can do a join using 'index' (require '[clojure.set :as s] '[clojure.core.reducers :as r]) (def ds1 [{:id 1 :name "name1"} {:id 2 :name "name2"} {:id 3 :name "name3"}]) (def ds2 [{:id 2 :address "addr2"} {:id 3 :address "addr3"} {:id 4 :address "addr4"}]) (into () (r/map #(r/reduce merge %) (vals (s/index (s/union ds2 ds1) [:id])))) ;; ({:id 1, :name "name1"} ;; {:id 4, :address "addr4"} ;; {:id 3, :name "name3", :address "addr3"} ;; {:id 2, :address "addr2", :name "name2"})
;; use index to query a data set (def data [{:gender "male", :age-group "child", :origin "Germany", :prename "Hans"} {:gender "male", :age-group "adult", :origin "France", :prename "Jacques"} {:gender "male", :age-group "senior", :origin "Estonia", :prename "Rasmus"} {:gender "male", :age-group "adult", :origin "Poland", :prename "Jakub"} {:gender "male", :age-group "senior", :origin "Germany", :prename "Uwe"} {:gender "female", :age-group "adult", :origin "France", :prename "Amélie"} {:gender "female", :age-group "child", :origin "Estonia", :prename "Sofia"} {:gender "female", :age-group "child", :origin "Germany", :prename "Emma"} {:gender "female", :age-group "child", :origin "Estonia", :prename "Alisa"} {:gender "female", :age-group "senior", :origin "Poland", :prename "Anna"}]) (def the-index (clojure.set/index data [:gender :origin])) ;; find all men originating from Germany: (get the-index {:gender "male" :origin "Germany"}) ;; => #{{:gender "male", :age-group "child", :origin "Germany", :prename "Hans"} {:gender "male", :age-group "senior", :origin "Germany", :prename "Uwe"}}
index