简体   繁体   English

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

[英]Clojure-How to add successive pairs in vector?

Trying to write a recursive function that adds successive pairs in a vector. 尝试编写一个递归函数,在向量中添加连续的对。

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

Pretty much stuck and this is what I have currently: 几乎卡住了,这就是我目前所拥有的:

(def tmp  [ 1 2 3 4])

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

This is wrong as it adds just the pairs and not successive pairs. 这是错误的,因为它只添加对而不是连续的对。 I get [3 7] instead of [3 5 7] 我得到[3 7]而不是[3 5 7]

Here is another possible solution: 这是另一种可能的解决方案

(def tmp [1 2 3 4])

(map + tmp (rest tmp))

Partition takes an extra argument specifying how far to step forward between each partition. 分区需要一个额外的参数来指定每个分区之间的前进距离。

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

(3 5 7 9)

You are asking for a recursive function, and even though in most cases set and list functions are preferable above crafting your own recursive function, this is not always possible. 你要求一个递归函数,尽管在大多数情况下set和list函数比制作你自己的递归函数更可取,但这并不总是可行的。 This problem is also very easy to write recursively in a idiomatic functional way, using an accumulator 使用累加器以惯用的函数方式递归地写这个问题也很容易

The idea is you start with an empty accumulator, and build your result step by step. 我们的想法是从空的累加器开始,逐步构建结果。 The accumulator ( acc in this code snippet) will hold the answer in the end. 累加器(此代码段中的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)))

What happens here? 这里发生了什么? You pass vector [1 2 3 4] to v1 . 您将矢量[1 2 3 4]传递给v1 Then the loop starts and in it , two variables are initialized : 然后循环开始并在其中初始化两个变量:

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

Simply enough the sum of the first two elements (+ (first the-list) (second the-list) are added to the accumulator. Then with recur the loop is called again passing the rest of the list (rest the-list) and the accumulator, now holding 3 (being the sum of the two first elements). The new vaues are : 简单地说,前两个元素的总和(+ (first the-list) (second the-list)被添加到累加器。然后使用recur再次调用循环通过列表的其余部分(rest the-list)和累加器,现在持有3(是两个第一个元素的总和)。新的vaues是:

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

next steps : 下一步 :

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

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

Then the if condition no longer holds and the else clause is returned (conveniently being the accumulator, now holding the solution). 然后if条件不再成立并返回else子句(方便地是累加器,现在持有解决方案)。

General idea 大概的概念

You start out with an empty accumulator and your input set. 首先是一个空累加器和输入集。 Each step, the accumulator builds up. 每一步,累加器都会建立起来。 In most cases, the input set is getting smaller each step too. 在大多数情况下,输入集也逐渐变小。 Then some if-condition is met and the accumulator returns. 然后满足一些if条件并且累加器返回。

Also very classic in this particular problem is that the input set is loosing its first element each step. 在这个特殊问题中,非常经典的是输入集在每一步都失去了它的第一个元素。 (rest ) is very practical here ( cdr in most other lisps). (休息)在这里非常实用(大多数其他lisps中的cdr)。

general form 一般形式

The loop/recur form in clojure is very nice, but in a lot other languages, this syntax is lacking. clojure中的循环/重复形式非常好,但在很多其他语言中,缺少这种语法。 A very classical solution is to have two functions : one recursive that does the looping, and one with the same name, but other arity that does the initialization of the accumulator. 一个非常经典的解决方案是有两个函数:一个递归执行循环,一个具有相同的名称,但其他arity执行累加器的初始化。 Simpler in code than it is to explain, so here it is in some made up java-like syntax : 代码比解释更简单,所以这里有一些类似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]) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM