我无法在Clojure中找到按键值过滤地图列表的内置功能。例如,我们有以下列表:
user=> (def animals (list {:name "Charlie" :weight 350 :specie :elephant}
{:name "Vasya" :weight 250 :specie :bear}
{:name "John" :weight 200 :specie :elephant}
{:name "Monk" :weight 200 :specie :monkey}))
#'user/animals
我想选择所有:specie
值:elephant
的所有内容。我怎样才能做到这一点?我发现的最好的方法是:
user=> (defn filter-data [data m]
(let [k (keys m) v (vals m)]
(filter #(= (map % k) v) data)))
#'user/filter-data
user=> (clojure.pprint/print-table (filter-data animals {:specie :elephant}))
| :name | :weight | :specie |
|---------+---------+-----------|
| Charlie | 350 | :elephant |
| John | 200 | :elephant |
nil
有更好的方法吗?
答案 0 :(得分:6)
使用过滤器
可以轻松实现(clojure.pprint/print-table
(filter #(= (:specie %) :elephant) animals))
你总是可以将过滤器包装在一个函数中以获得不同的语法",例如:
(defn cool-filter [[k v] l]
(filter #(= (k %) v) l))
(clojure.pprint/print-table
(cool-filter [:specie :elephant] animals))
答案 1 :(得分:4)
您还可以使用功能组合:
(filter (comp (partial = :elephant) :specie) animals)
...或
(filter (comp #{:elephant} :specie) animals)
答案 2 :(得分:3)
虽然filter
解决方案显然是最直接的,但我想在需要查找多个物种的情况下添加替代方案:
(def grouped-animals (group-by :specie animals))
(:elephant grouped-animals)
; [{:name "Charlie", :weight 350, :specie :elephant} {:name "John", :weight 200, :specie :elephant}]