我今天一直在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)))
我可以使用一些关于如何思考几个问题的指示。
如何确保我不更改结果列表的顺序? cons
和conj
都添加元素,无论哪里添加元素最有效(在列表的开头,向量的末尾等),所以我看不出我应该如何使用通用序列时对此有任何控制。
如何处理不同类型的嵌套序列?例如,输入'(1 2 [3 4])
将输出([3 4] 2 1)
,输入[1 2 '(3 4)]
将输出(4 3 2 1)
我是否从“正确”角度接近这个?我应该使用带累加器的递归内部函数来执行此操作,还是我遗漏了一些明显的东西?
答案 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)))