简体   繁体   English

如何有条件地与clojure向量联合

[英]How do I conj to a clojure vector conditionally

Is there a cleaner way to do something like the following in clojure? 在clojure中有更清洁的方法来执行以下操作吗?

(defn this [x] (* 2 x))
(defn that [x] (inc x))
(defn the-other [x] (-> x this that))

(defn make-vector [thing]
  (let [base (vector (this (:a thing))
                     (that (:b thing)))]
    (if-let [optional (:c thing)]
      (conj base (the-other optional))
      base)))

(make-vector {:a 1, :b 2}) ;=> [2 3]
(make-vector {:a 1, :b 2, :c 3}) ;=> [2 3 7]

By "cleaner" I mean something closer to this: 通过“清洁”,我的意思是更接近这个:

(defn non-working-make-vector [thing]
  (vector (this (:a thing))
          (that (:b thing))
          (if (:c thing) (the-other (:c thing)))))

(non-working-make-vector {:a 1, :b 2} ;=> [2 3 nil]  no nil, please!
(non-working-make-vector {:a 1, :b 2, :c 3} ;=> [2 3 7]

Note that I might want to call some arbitrary function (eg this , that , the-other ) on any of the keys in thing and place the result in the returned vector. 请注意,我可能想要在thing任何键上调用一些任意函数(例如thisthatthe-other ),并将结果放在返回的向量中。 The important thing is that if the key doesn't exist in the map it should not put a nil in the vector. 重要的是,如果地图中不存在密钥,则不应在向量中添加nil

This is similar to this question but the output is a vector rather than a map so I can't use merge . 这类似于这个问题,但输出是矢量而不是地图,所以我不能使用merge

(defn this [x] (* 2 x))
(defn that [x] (inc x))
(defn the-other [x] (-> x this that))

(def k-f-map {:a this
              :b that
              :c the-other})

(def m1 {:a 1 :b 2})
(def m2 {:a 1 :b 2 :c 3})

(defn make-vector [k-f-map m]
  (reduce (fn [res [fk fv]]
            (if (fk m)
              (conj res (fv (fk m)))
              res))
          [] k-f-map))

(make-vector k-f-map m1)
-> [2 3]

(make-vector k-f-map m2)
-> [2 3 7]
;;; replace [:a :b :c] with a vector of arbitrary functions
;;; of your choice, or perhaps accept a seqable of functions
;;; as an extra argument
(defn make-vector [thing]
  (into [] (keep #(% thing) [:a :b :c])))

;;; from the REPL:
(make-vector {:a 1 :b 2})
; => [1 2]
(make-vector {:a 1 :b 2 :c 3})
; => [1 2 3]

Note that keep only throws out nil ; 请注意, keep只抛出nil ; false will be included in the output. false将包含在输出中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM