Given a vector of maps:

(def my-list
  [{:a 1 :b 2 :c 3}
    {:a 1 :b 5 :c 6}
    {:a 7 :b 8 :c 12}
    {:a 10 :b 11 :c 12}])

and a blacklist:

(def blacklist
  [{:a 1 :c 3}
    {:a 10 :c 12}])

the expected output is:

[{:a 1 :b 5 :c 6}
  {:a 7 :b 8 :c 12}]

I came up with:

(defn not-excluded?
  [blacklist item]
  (not-any? (fn [exclusion-item]
              (and (= (:a item) (:a exclusion-item))
                   (= (:c item) (:c exclusion-item))))

(filter (partial not-excluded? blacklist) my-list)

but there is probably a more idiomatic Clojure way.

  • \$\begingroup\$ I don't Clojure very well, but requiring :a and :c to be hardcoded in the function doesn't look like a good solution. Have you considered passing those as arguments instead? \$\endgroup\$
    – Mast
    Nov 26, 2019 at 15:01
  • \$\begingroup\$ Yeah, that's one thing, that can be improved for sure. 👍 \$\endgroup\$ Nov 26, 2019 at 15:54

1 Answer 1


We want to exclude from the vector (more generally a sequence) the maps of which any map in the blacklist is a sub-map. Let's define a function that tests whether its first argument is a sub-map of its second argument:

(defn submap? [a b]
  (every? (fn [[k v]] (= v (b k)))  a))

For instance,

=> (map #(submap? {1 2} %) [{} {1 1} {1 2}])
(false false true)

So far, so good. Let's use submap? to define function clean that takes a blacklist and a sequence of maps as arguments, excluding any supermaps of any map in the blacklist from the sequence:

(defn clean [blacklist ms]
    (fn [m] (not-any? #(submap? % m) blacklist))

For example,

=> (clean blacklist my-list)
({:a 1, :b 5, :c 6} {:a 7, :b 8, :c 12})

submap? could be careful about absent keys. If you have nil values, you need to fix this.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.