3

我今天一直在解决4Clojure上的问题,但在问题 28上遇到了麻烦,实现了 flatten。

我的代码有几个明确的问题。

(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. 如何确保我没有更改结果列表的顺序?cons并且conj两者都在添加元素最有效的地方添加元素(在列表的开头,在向量的末尾等),所以我看不出在使用泛型时我应该如何控制它序列。

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

  3. 我什至是从“正确”的角度来解决这个问题吗?我应该使用带有累加器的递归内部函数来做到这一点,还是我错过了一些明显的东西?

4

4 回答 4

8

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

(defn flatten [coll]
  (if (sequential? coll)
    (mapcat flatten coll)
    (list coll)))
于 2013-04-23T08:56:29.123 回答
2

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

您需要的只是首先休息和一些递归解决方案。

于 2013-04-22T20:10:37.653 回答
1

一种可能的方法:

(defn flatten [[f & r]]
  (if (nil? f)
    '()
    (if (sequential? f)
      (concat (flatten f) (flatten r))
      (cons f (flatten r)))))
于 2013-04-23T05:40:32.353 回答
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)))
于 2016-05-19T20:27:27.910 回答