2016-11-17 30 views
1

我无法在Clojure中找到内置功能,以按键的值过滤地图列表。例如,我们有一个下面的列表:通过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

你应该改一下你的问题做出更清楚你想要的功能,接收的地图,比如'{:种类:大象'',否则可能会认为你只是想用一个简单的谓词进行过滤。 – Setzer22

+0

如果要在地图中添加更多绑定键/值,您的功能就可以了 –

回答

5

这可以很容易地过滤

(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)) 
3

虽然filter解决方案显然是最直接的,我想添加一个替代的情况下,你需要查找超过一个物种:

(def grouped-animals (group-by :specie animals)) 
(:elephant grouped-animals) 
; [{:name "Charlie", :weight 350, :specie :elephant} {:name "John", :weight 200, :specie :elephant}] 
+0

这可以做更多的工作,但这是一个有趣的选择。 – jszakmeister

2

您还可以使用功能组成:

(filter (comp (partial = :elephant) :specie) animals) 

或...

(filter (comp #{:elephant} :specie) animals) 
相关问题