2016-11-17 1 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)