如何有条件地连接到clojure向量

如何有条件地连接到clojure向量,clojure,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

在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]
我所说的“清洁剂”是指与此更接近的东西:

(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]
请注意,我可能希望对
thing
中的任何键调用任意函数(例如
this
that
另一个
),并将结果放入返回的向量中。重要的是,如果键在映射中不存在,则不应在向量中放置
nil

这与类似,但输出是矢量而不是贴图,因此我无法使用
merge

;;; 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]

注意
keep
只抛出
nil
false
将包含在输出中。

难道你不想要(vec(vals thing))?@DiegoBasch:是的,这就是他想要的。不,对不起@DiegoBasch,我想要能够调用给定键上的任意函数。我对示例进行了编辑,以使其更加清晰。如果
错误
也应被丢弃,请使用
(筛选标识(映射(%thing))
代替
保留
调用。请参阅我的编辑。可以使用
keep
调用任意函数吗?我想我可以有一些伞形函数来分配密钥名,但这开始变得难看。正如答案中提到的,你可以在传递给
keep
的sequalable中放入任意函数
make vector
。特别是,您可以将
[:a:b:c]
替换为
[(comp this:a)(comp that:b)(comp the other:c)]
,以获得当前包含在问题文本中的
非工作生成向量的版本,该版本实际上在输出中省略了任何
nil
。(或者你可以把
(comp this:a)
拼成
#(this(:a%))
,当然。)另请参见
(doc keep)
(基本上它的工作原理类似于
map
,但从输出中丢弃
nil
)。嗯,这并不是我想要的。我的例子不好。完全重新编辑问题或删除问题并重新提问更好吗?好的,如果我理解正确,您希望在对值调用函数之前进行过滤(以查看是否存在键)(因此您不希望调用
那个
另一个
,从您的
nil
示例中)。在这种情况下,mobyte的答案应该适合你。这可能就是stand所寻找的答案。作为一个小调整,在Clojure 1.4
reduce kv
中,它更适合这项工作。
(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]