Add repeated-keys utility.

This commit is contained in:
Richard Newman 2016-10-27 11:37:02 -07:00
parent df378cee81
commit 7e50528788
2 changed files with 34 additions and 0 deletions

View file

@ -174,3 +174,22 @@
(let [[k v] (f x)]
(assoc! ret k (conj (get ret k []) v))))
(transient {}) coll)))
(defn repeated-keys
"Takes a seq of maps.
Returns the set of keys that appear in more than one map."
[maps]
(if (not (seq (rest maps)))
#{}
;; This is a perfect use case for transients, except that
;; you can't use them for intersection due to CLJ-700.
;; http://dev.clojure.org/jira/browse/CLJ-700
(loop [overlapping #{}
seen #{}
key-sets (map (comp set keys) maps)]
(if-let [ks (first key-sets)]
(let [overlap (clojure.set/intersection seen ks)]
(recur (clojure.set/union overlapping overlap)
(clojure.set/union seen ks)
(rest key-sets)))
overlapping))))

View file

@ -51,3 +51,18 @@
(are [m xs] (= m (util/group-by-kv identity xs))
{:a [1 2] :b [3]}
[[:a 1] [:a 2] [:b 3]]))
(deftest test-repeated-keys
(let [abc {:a 1 :b 2 :c 3}
def {:d 1 :e 2 :f 3}
bcd {:b 1 :c 2 :d 3}
efg {:e 1 :f 2 :g 3}
empty {}]
(is (= #{} (util/repeated-keys [])))
(is (= #{} (util/repeated-keys [empty])))
(is (= #{} (util/repeated-keys [empty empty])))
(is (= #{} (util/repeated-keys [abc empty empty])))
(is (= #{} (util/repeated-keys [abc def empty])))
(is (= #{:b :c} (util/repeated-keys [bcd abc])))
(is (= #{:b :c :d} (util/repeated-keys [abc def bcd])))
(is (= #{:b :c :d :e :f :g} (util/repeated-keys [abc efg def efg bcd])))))