Clojure - 如何在向量中添加连续对?

时间:2014-12-16 02:06:57

标签: vector clojure sum

尝试编写一个递归函数,在向量中添加连续的对。

[1 2 3 4] => [3 5 7]

相当困难,这就是我目前所拥有的:

(def tmp  [ 1 2 3 4])

user> (map #(+ (second %) (first %)) (partition-all 2 tmp ))

这是错误的,因为它只添加对而不是连续对。我得到[3 7]而不是[3 5 7]

3 个答案:

答案 0 :(得分:8)

这是另一种可能的解决方案:

(def tmp [1 2 3 4])

(map + tmp (rest tmp))

答案 1 :(得分:7)

分区需要一个额外的参数来指定每个分区之间的前进距离。

(map #(apply + %) (partition 2 1 [1 2 3 4 5])) =>

(3 5 7 9)

答案 2 :(得分:1)

你要求一个递归函数,尽管在大多数情况下set和list函数比制作你自己的递归函数更可取,但这并不总是可行的。使用累加器

以惯用的功能方式递归写入这个问题也很容易

我们的想法是从空的累加器开始,逐步构建结果。累加器(此代码段中的 acc )最终会保留答案。

(defn add-pairs [v1]
  (loop [the-list v1  acc []]
    (if   (next the-list) ;; checks wether there's more than 1 left in the-list
      (recur (rest the-list ) 
             (conj  acc (+ (first the-list) (second the-list))))
     acc)))

这里发生了什么?您将向量[1 2 3 4]传递给v1。 然后循环开始并在其中初始化两个变量:

the-list <- [1 2 3 4]
acc []

只需将前两个元素(+ (first the-list) (second the-list)的总和添加到累加器即可。然后使用recur再次调用循环传递列表的其余部分(rest the-list)和累加器,现在保持3(是两个第一个元素的总和)。新的vaues是:

the-list <- [2 3 4]
acc [3]

后续步骤:

the-list <- [3 4]
acc [3 5]

the-list <- [4]
acc [3 5 7]

然后if条件不再成立并返回else子句(方便地是累加器,现在持有解决方案)。

一般想法

您从一个空的累加器和输入集开始。每一步,累加器都会建立起来。在大多数情况下,输入集也逐渐变小。然后满足一些if条件并且累加器返回。

在这个特殊问题中,非常经典的是输入集在每一步都失去了它的第一个元素。 (休息)在这里非常实用(大多数其他lisps中的cdr)。

一般表格

clojure中的循环/重复形式非常好,但在很多其他语言中,缺少这种语法。一个非常经典的解决方案是有两个函数:一个递归执行循环,一个具有相同的名称,但其他arity执行累加器的初始化。代码比解释更简单,所以这里有一些类似于java的语法:

function add-pairs(v1 acc) {
   if (cond)
      //do stuff to v1 and acc
      add-pairs(v1 acc)
   else 
      return acc }

function add-pairs(v1) {
   return add-pairs(v1,[])
}

var result = add-pairs([42 666 1447])