如何创建一个在向量中的每对元素之间插入元素的函数

时间:2017-07-02 09:23:12

标签: clojure

我想编写一个在向量中的现有元素之间插入元素的函数。插入的元素是前面和后面的元素的函数,第一个和最后一个元素保持不受影响。

E.g。我希望插入的元素是前面和后面的元素的平均值:

输入:

  

[1 10 15]

输出:

  

[1 5.5 10 12.5 15]

在Clojure中执行此操作的最佳方法是什么?

4 个答案:

答案 0 :(得分:4)

这是另一种方式:

(defn insert-mean-between [xs]
  (let [f (fn [x y]
            [(* (+ x y) 0.5) y])]
    (->> xs
         (partition 2 1)
         (mapcat (partial apply f))
         (cons (first xs))
         vec)))

(insert-mean-between [1 10 15])
;;=> [1 5.5 10 12.5 15]

技巧f正在返回答案和RHS输入。这样,他们将在没有重复的情况下组合在一起。您将遇到的唯一问题是缺少第一个元素。所以我们只是把它放在前面。从一开始我们就必须知道,当我们选择返回RHS而不是LHS时,cons将是一个方便的操作。

计算均值只是一个例子,一个改进的解决方案是插入独立于均值/任何函数:

(defn calc-mean [x y] (* (+ x y) 0.5) 
(insert-between calc-mean [1 10 15])

然后更通用的插入功能可能是:

(defn insert-between [g xs]
  (->> xs
       (partition 2 1)
       (mapcat (fn [[x y]] [(g x y) y]))
       (cons (first xs))))

答案 1 :(得分:4)

并且在没有递归延迟序列生成的情况下,变体列表不会完整:

(defn with-avg [[x1 & [x2 :as tail] :as items]]
  (when (seq items)
    (if (seq tail)
      (lazy-cat [x1 (/ (+ x1 x2) 2)] (with-avg tail))
      [x1])))

user> (with-avg [1 2 3 4 5])
;;=> (1 3/2 2 5/2 3 7/2 4 9/2 5)
user> (with-avg [1])
;;=> [1]
user> (with-avg [])
;;=> nil
user> (with-avg [1 2])
;;=> (1 3/2 2)
user> (with-avg [1 2 3])
;;=>(1 3/2 2 5/2 3)

答案 2 :(得分:0)

我可以解决的一种方法是将模式匹配Vector设为f s t,我假设它有3个元素

然后创建变量以分配第一个中位数first + second / 2和第二个中位数second + third /2

最后返回一个新的Vector,其中包含您想要的组合。

示例,(我使用lein REPL

user=> (defn insert_medians[vect]
  #_=>    (let [[f s t] vect
  #_=>       m1 (float (/ (+ f s) 2))
  #_=>       m2 (float (/ (+ s t) 2))]
  #_=>       [f m1 s m2 t]))
#'user/insert_medians

user=> (insert_medians [1 10 15])
[1 5.5 10 12.5 15]

如果矢量大于3个元素,则需要先找到所有中位数,然后使用interleave fn插入原始矢量。

答案 3 :(得分:0)

(defn insert-between
  "Inserts elements between existing elements in a vector v. The inserted
  elements are a result of applying the function f to the elements that precede
  and succeed it, with the first and last elements of v remaining unaffected."
  [f [x & xs :as v]]
  (->> (partition 2 1 v)
       (mapcat (fn [[a b]] [(f a b) b]))
       (cons x)
       (into [])))

(defn mean [& numbers]
  (float (/ (apply + numbers) (count numbers))))

(insert-between mean [1 10 15])    ; => [1 5.5 10 10 12.5 15]
(insert-between + [1 10 15 20 25]) ; => [1 11 10 25 15 35 20 45 25]
(insert-between mean [])           ; => [nil] :(
相关问题