如何在Clojure中按值的真实性并行过滤数据?

时间:2019-11-19 07:36:11

标签: dictionary filter clojure reduce clojurescript

我们有一些像这样的数据:

(def x {:title ["NAME" "CODE" "ORDER" "MIN" "MAX" "IMG"]
        :show-in-list [true true true true false false]
        :key [:name :code :order :min :max :image]
        :input-type [:txt :txt :num :num :num :img]
        :value [nil nil nil nil nil nil]
        :required [true true false false false false]})

我们想用:required的布尔值过滤这些值,从而得出:

{:title ["NAME" "CODE"],
 :show-in-list [true true],
 :key [:part_name :part_code],
 :input-type [:txt :txt],
 :value [nil nil],
 :required [true true]}

3 个答案:

答案 0 :(得分:1)

您可以使用':required'向量过滤每个元素:

(let [x {:title        ["NAME" "CODE" "ORDER" "MIN" "MAX" "IMG"]
         :show-in-list [true false true true false false]
         :key          [:name :code :order :min :max :image]
         :input-type   [:txt :txt :num :num :num :img]
         :value        [nil nil nil nil nil nil]
         :required     [true true false false false false]}]
  (->> x
       (map (fn [[k v]]
              ;; value v (which is a vector) is filtered out by its :required filter
              [k  (->> (map #(if %1 %2 ::false) (:required x) v)
                       ;; remove ::false element
                       (remove #(= ::false %)))]))
       ;; add the updated key-value pair
       (into (empty x))))

返回...

{:title        ("NAME" "CODE"),
 :show-in-list (true false),
 :key          (:name :code),
 :input-type   (:txt :txt),
 :value        (nil nil),
 :required     (true true)}

答案 1 :(得分:1)

我会建议稍微不同的方法: 既然您已经需要过滤掉这种“打包”数据结构中的数据,我想您可能还需要对它进行一些其他操作,那么将数据结构打包/分解为单独的地图会更好吗?

它可能看起来像这样:

(defn decompose [data]
  (let [ks (keys data)]
    (apply map #(zipmap ks %&) (vals data))))

这是一个解包数据:

user> (decompose x)


({:title "NAME",
  :show-in-list true,
  :key :name,
  :input-type :txt,
  :value nil,
  :required true}
 {:title "CODE",
  :show-in-list true,
  :key :code,
  :input-type :txt,
  :value nil,
  :required true}
  ;;....more maps
)

然后recompose

(defn recompose [data]
  (when (seq data)
    (apply merge-with
           conj
           (zipmap (keys (first data)) (repeat []))
           data)))

这又反过来打包未打包的数据。

因此,现在只需过滤分解的数据并将其重新组合即可完成您的任务:

(->> x
     decompose
     (filter :required)
     recompose)

;;=> {:title ["NAME" "CODE"],
;;    :show-in-list [true true],
;;    :key [:name :code],
;;    :input-type [:txt :txt],
;;    :value [nil nil],
;;    :required [true true]}

在我看来,它看起来更笼统,(更重要的是)可读性更高。

答案 2 :(得分:0)

(defn bar [state [required value]]
  (if required (conj state value) state))

(defn foo [required values]
  (reduce bar [] (map vector required values)))

(zipmap (keys x) (map #(foo (:required x) %) (vals x)))
  

我们要通过:required的bool值过滤这些值

需要配对并附加值,如果需要,则将值添加到新集合