Clojure:我实施flatten有什么问题?

时间:2013-04-22 19:57:04

标签: clojure functional-programming

我今天一直在4Clojure处理问题,我在Problem 28遇到了麻烦,实施了扁平化。

我的代码存在一些明确的问题。

(fn [coll]
  ((fn flt [coll res]
    (if (empty? coll)
        res
        (if (seq? (first coll))
            (flt (into (first coll) (rest coll)) res)
            (flt (rest coll) (cons (first coll) res))))) coll (empty coll)))

我可以使用一些关于如何思考几个问题的指示。

  1. 如何确保我不更改结果列表的顺序? consconj都添加元素,无论哪里添加元素最有效(在列表的开头,向量的末尾等),所以我看不出我应该如何使用通用序列时对此有任何控制。

  2. 如何处理不同类型的嵌套序列?例如,输入'(1 2 [3 4])将输出([3 4] 2 1),输入[1 2 '(3 4)]将输出(4 3 2 1)

  3. 我是否从“正确”角度接近这个?我应该使用带累加器的递归内部函数来执行此操作,还是我遗漏了一些明显的东西?

4 个答案:

答案 0 :(得分:8)

你应该尝试尽可能多地使用HOF(更高阶函数):它更清楚地传达你的意图,并使你免于引入微妙的低级错误。

(defn flatten [coll]
  (if (sequential? coll)
    (mapcat flatten coll)
    (list coll)))

答案 1 :(得分:2)

关于列表和向量的问题。正如您在测试中看到的那样,输出是列表。只需做出正确的抽象。幸运的是,clojure已经有一个名为序列

您只需第一次休息以及一些递归解决方案。

答案 2 :(得分:1)

一种可能的方法:

(defn flatten [[f & r]]
  (if (nil? f)
    '()
    (if (sequential? f)
      (concat (flatten f) (flatten r))
      (cons f (flatten r)))))

答案 3 :(得分:1)

以下是如何在一次迭代中以尾调用优化方式执行此操作,并尽可能使用最少量的Clojure.core代码:

#(loop [s % o [] r % l 0]
   (cond
    (and (empty? s) (= 0 l))
    o
    (empty? s)
    (recur r
           o
           r
           (dec l))
    (sequential? (first s))
    (recur (first s)
           o
           (if (= 0 l)
             (rest s)
             r)
           (inc l))
    :else
    (recur (rest s)
           (conj o (first s))
           r
           l)))