尝试编写一个递归函数,在向量中添加连续的对。
[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]
答案 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])