在Clojure中递归反转序列

时间:2011-12-06 03:39:49

标签: recursion clojure

我想在不使用reverse函数的情况下反转Clojure中的序列,并以递归方式执行此操作。

以下是我提出的建议:

(defn reverse-recursively [coll]
  (loop [r (rest coll)
         acc (conj () (first coll))]
    (if (= (count r) 0)
      acc
      (recur (rest r) (conj acc (first r))))))

示例输出:

user> (reverse-recursively '(1 2 3 4 5 6))
(6 5 4 3 2 1)
user> (reverse-recursively [1 2 3 4 5 6])
(6 5 4 3 2 1)
user> (reverse-recursively {:a 1 :b 2 :c 3})
([:c 3] [:b 2] [:a 1])

问题:

  1. 有没有更简洁的方法,即没有循环/重复?
  2. 如果没有在循环中使用“accumulator”参数,有没有办法做到这一点?

  3. 参考文献:

    Whats the best way to recursively reverse a string in Java?

    http://groups.google.com/group/clojure/browse_thread/thread/4e7a4bfb0d71a508?pli=1

7 个答案:

答案 0 :(得分:24)

  • 你不需要数数。当剩下的序列为空时停止。
  • 您不应预先填充acc,因为原始输入可能为空(并且代码更多)。
  • 解构很酷。
(defn reverse-recursively [coll]
  (loop [[r & more :as all] (seq coll)
         acc '()]
    (if all
      (recur more (cons r acc))
      acc)))

对于loop / recuracc,您需要一些传递工作逆转列表的方法。它可以是loop,也可以在函数中添加另一个参数(这正是loop正在做的事情。)

或使用更高阶的功能:

user=> (reduce conj '() [1 2 3 4])
(4 3 2 1)

答案 1 :(得分:4)

为了详尽无遗,还有一种使用into的方法。由于内部使用conj,因此可以按如下方式使用:

(defn reverse-list 
  "Reverse the element of alist."
  [lst]
  (into '() lst))

答案 2 :(得分:3)

对问题1是肯定的,这就是我对递归公式的回答(我无法告诉你这是否是一个好的clojure练习)。

(defn recursive-reverse [coll]
    (if (empty? coll)
        []
        (conj (recursive-reverse (rest coll)) (first coll) )))

答案 3 :(得分:2)

在当前版本的Clojure中,有一个名为rseq的内置函数。对于经过的人。

答案 4 :(得分:0)

(defn my-rev [col]
  (loop [ col col
          result []]
        (if (empty? col)
            result
            (recur (rest col) (cons (first col) result)))))

<强> Q1。

JVM无法优化递归,这是一种直接和堆栈溢出的递归函数。因此,在使用loop / recur的Clojure中。因此,不使用无法定义重复深度递归的函数。 (它也在内部用作功能蹦床。)

<强> Q2。

recur的递归函数,必须是尾递归的。如果正常的递归函数改为tail-recursive函数,那么需要携带一个变量值作为累加器。

答案 5 :(得分:0)

(defn reverse-seq [sss]
  (if (not (empty? sss))
    (conj (reverse-seq (rest sss)) (first sss))
  )
)

答案 6 :(得分:0)

g/s = O(f/r)