更新答案
您可以使用list comprehension 来检查集合中每个模式的每个项目。
(defn- all-occurrences [xs patterns]
(for [x xs
pattern patterns
:when (clojure.string/includes? (:type x) pattern)]
[(keyword pattern) x]))
或者使用你的filter-response函数:
(defn- all-occurrences [xs patterns]
(for [pattern patterns
x (filter-response xs pattern)]
[(keyword pattern) x]))
然后使用reduce 和update 将出现的列表合并到一个地图中:
(defn group-by-patterns [xs patterns]
(reduce (fn [m [pattern text]] (update m pattern conj text))
{}
(all-occurrences xs patterns)))
用新的输入调用它:
(def xs
[{:name "Apple" :type "Fruit is a type"}
{:name "Tomato" :type "Vegetable are food"}
{:name "Pear" :type "the type can also be Fruit"}
{:name "Steak" :type "eat less Meat"}])
(group-by-patterns xs ["Fruit" "Vegetable"])
=> {:Fruit ({:name "Pear", :type "the type can also be Fruit"} {:name "Apple", :type "Fruit is a type"}),
:Vegetable ({:name "Tomato", :type "Vegetable are food"})}
原答案
首先您可以使用group-by 对指定键下的值进行分组:
(def xs
[{:name "Apple" :type "Fruit"}
{:name "Tomato" :type "Vegetable"}
{:name "Pear" :type "Fruit"}
{:name "Steak" :type "Meat"}])
erdos=> (group-by :type xs)
{"Fruit" [{:name "Apple", :type "Fruit"} {:name "Pear", :type "Fruit"}],
"Vegetable" [{:name "Tomato", :type "Vegetable"}],
"Meat" [{:name "Steak", :type "Meat"}]}
然后使用select-keys 过滤键:
erdos=> (select-keys (group-by :type xs) ["Fruit" "Vegetable"])
{"Fruit" [{:name "Apple", :type "Fruit"} {:name "Pear", :type "Fruit"}],
"Vegetable" [{:name "Tomato", :type "Vegetable"}]}
如果需要关键字键,则需要额外的映射步骤:
erdos=> (into {}
(for [[k v] (select-keys (group-by :type xs) ["Fruit" "Vegetable"])]
[(keyword k) v]))
{:Fruit [{:name "Apple", :type "Fruit"} {:name "Pear", :type "Fruit"}],
:Vegetable [{:name "Tomato", :type "Vegetable"}]}