我有一个向量v
(def v [1 2 5 8 4 3 8 9 3])
我想应用函数myfn
(defn myfn [x] (+ 1 x))
选择我的索引为idx
(def idx [3 5])
我见过How do I modify a portion of a vector in Clojure?,这并不是我所需要的。
就像你在MATLAB中做的那样
v = [1 2 5 8 9 3];
idx = [3 5];
v(idx) = myfn(v(idx));
答案 0 :(得分:9)
clojure中的向量是关联的,因此您可以执行以下操作:(reduce #(update-in %1 [%2] myfn) v idx)
答案 1 :(得分:3)
更新,因为我误解了这个问题。
这是另一种解决方案:
(apply assoc v (mapcat #(vector % (myfn (v %))) idx))
即,为assoc
建立索引/新值对的参数列表。我认为mange的解决方案可能更好。
原创,错误的解决方案
不要忘记向量v
本身就是其索引的函数。所以:
(map myfn (map v idx))
或:
(->> idx (map v) (map myfn))
或:
(map (comp myfn v) idx)
我确信还有一个非常聪明的答案涉及juxt
:)
答案 2 :(得分:2)
你提到“一个[大]矢量”,所以你关心性能吗?您可能想了解transients:
(persistent!
(reduce (fn [v i] (assoc! v i (myfn (get v i))))
(transient v)
idx))
或者,如果您更喜欢循环风格,这也会做同样的事情:
(loop [v (transient v), [i & is :as idx] idx]
(if (empty? idx)
(persistent! v)
(recur (assoc! v i (myfn (get v i))) is)))
答案 3 :(得分:0)
(let [sidx (set idx)]
(vec ;(sidx i)
(map-indexed (fn [i x] (if (contains? sidx i) (myfn x) x)) v)))