Reputation: 9778
I have a collection that I want to filter. The filter is done using a map where the key is the attribute in a collection item, and the value is what the collection items should match. Example:
(let [filters {:name "test"
:type "new"}
collection [{:name "testable" :type "old"}
{:name "shoudwork" :type "new"}
{:name "testable" :type "new"}]])
Right now, I have built my filter function to only take a single attribute and value. I want to expand it to actually be able to take a filter hashmap
.
This is what my current filter looks like:
(filter #(re-find (re-pattern "test") (string/lower-case (% :name))) collection)
In other words, I want the filter
to not take "test
" hardcoded, but it should be the value from the filters
let binding, and the (% :name)
to not be hardcoded to :name
, but be the key from filters
let binding.
Upvotes: 2
Views: 540
Reputation: 17849
you can also use transducers:
;; first you create a filtering step factory for transduction:
(defn make-filter [[k v]]
(filter #(re-find (re-pattern v)
(clojure.string/lower-case (k %)))))
;; and then transform the collection:
(let [filters {:name "test"
:type "new"}
collection [{:name "testable" :type "old"}
{:name "shoudwork" :type "new"}
{:name "testable" :type "new"}]]
(sequence (reduce comp (map make-filter filters)) collection))
Upvotes: 3
Reputation: 8591
Create a function that returns the filtering function for a single [key expected-value]:
(defn regex-value [[k expected-rex]]
(fn [c] (re-find (re-pattern expected-rex)
(clojure.string/lower-case (get c k)))))
Create a function that will create the compounded filtering condition:
(defn build-filter [filters]
(apply every-pred (map regex-value filters)))
Use it:
(let [filters {:name "test"
:type "new"}
collection [{:name "testable" :type "old"}
{:name "shoudwork" :type "new"}
{:name "testable" :type "new"}]]
(filter (build-filter filters) collection))
Upvotes: 3