Created
December 20, 2012 16:23
-
-
Save alexpw/4346395 to your computer and use it in GitHub Desktop.
Seq utilities for grouping and indexing.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn group-by-with | |
"A group-by factory that accepts a combiner-fn to control how the values | |
of the grouping fn are collected." | |
[combiner-fn] | |
(fn [f coll] | |
(persistent! | |
(reduce | |
(fn [ret x] | |
(let [k (f x)] | |
(assoc! ret k (combiner-fn (get ret k) x)))) | |
(transient {}) coll)))) | |
;; A modified group-by that does not create a vector of grouped elements; | |
;; instead, only one element can be the mapped value. | |
(def group-by-one (group-by-with (fn [xs x] x))) | |
(def group-by-set (group-by-with (fn [xs x] | |
(if (nil? xs) | |
(set x) | |
(conj xs x))))) | |
(defn index-by-with | |
"A index-by factory that accepts a combiner-fn to control how the values | |
of the grouping fn are collected." | |
[combiner-fn] | |
(fn self | |
([coll f] (combiner-fn f coll)) | |
([coll f & fs] | |
(persistent! | |
(reduce | |
(fn [ret [k els]] | |
(assoc! ret k (apply self els fs))) | |
(transient {}) | |
(group-by f coll)))))) | |
;; Returns a nested hash map of the elements of coll keyed by the result of | |
;; any number of functions on the elements. The leaves will be a vector of | |
;; elements from the coll, just like a regular group-by. | |
(def index-by (index-by-with group-by)) | |
;; Returns a nested hash map of the elements of coll keyed by the result of | |
;; any number of functions on the elements, to create a nested hash map | |
;; where the leaves are a single value, instead of a vector, like group-by. | |
;; Warning, assumes that the set of supplied functions will reduce the | |
;; coll down to a single element; otherwise, the value will be last element. | |
(def index-by-unique (index-by-with group-by-one)) | |
;; Same as above but the leaves are combined into a set. | |
(def index-by-set (index-by-with group-by-set)) | |
;; Examples | |
(comment | |
(facts | |
(index-by-unique [{:a 1} {:a 2}] :a) => {1 {:a 1} | |
2 {:a 2}} | |
(index-by-unique [{:a 1 :b 2} {:a 2 :b 1}] :a) => {1 {:a 1 :b 2} | |
2 {:a 2 :b 1}} | |
(index-by-unique [{:a 1 :b 2} {:a 2 :b 1}] :a :b) => {1 {2 {:a 1 :b 2}} | |
2 {1 {:a 2 :b 1}}}) | |
(facts | |
(index-by [{:a 1} {:a 2}] :a) => {1 [{:a 1}] | |
2 [{:a 2}]} | |
(index-by [{:a 1 :b 2} {:a 2 :b 1}] :a) => {1 [{:a 1 :b 2}] | |
2 [{:a 2 :b 1}]} | |
(index-by [{:a 1 :b 2} {:a 2 :b 1}] :a :b) => {1 {2 [{:a 1 :b 2}]} | |
2 {1 [{:a 2 :b 1}]}})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment