Clojure的新手。
Input - ["a" ["b" "c"] "d"]
Expected output - ["a" "b" "c" "d"]
我尝试做的事情 - 创建一个空的向量('结果'),然后在输入集合上做两个剂量以填充结果'起来,最后回复填满的结果'。但是该函数返回一个空向量。我做错了什么?
(flat ["a" ["b" "c"] "d"])
(defn flat [arr]
(let [result []]
(doseq [element arr]
(if (coll? element) (doseq [element2 element] (conj result element2))
(conj result element))) result))
答案 0 :(得分:1)
正如其他人所指出的,你不能改变结果。如果你确实想要用变异来实现你的函数,你需要一个原子,你可以用swap来变异!
(defn flat [arr]
(let [result (atom [])]
(doseq [element arr]
(if (coll? element) (doseq [element2 element] (swap! result conj element2))
(swap! result conj element)))
@result))
但请注意,这只会给您一个单一的展平程度,您只需使用
即可完成(apply concat <your seq>)
一个简单的,递归的,多层次的扁平化是:
(defn flat [x] (if (coll? x) (mapcat flat x) [x]))
答案 1 :(得分:0)
#!/usr/bin/env boot
(def inp ["a" "b" ["c" "d" "e" ["f" "g" "h"] "i"] "j" "k"])
(defn flat
([xs] (flat xs []))
([xs acc]
(if (empty? xs) acc
(if (vector? (first xs))
(flat (rest xs) (flat (first xs) acc))
(recur (rest xs) (conj acc (first xs)))))))
(println (flat inp)) ;[a b c d e f g h i j k]
基本思想是检查第一个元素是否是一个列表,如果这样,则递归该列表(flat (first xs) acc)
将每个元素添加到累加器,然后继续给出(flat (rest xs) (flat (first xs) acc))
列表的其余部分。否则只会重复个别因素。
我们也可以使用其他结构,例如let
,cond
。
答案 2 :(得分:0)
如果你想要一个快速版本的flatten,请参阅clojure.core.reducers / flatten。
(require '[clojure.core.reducers :as r])
(defn rflatten [coll] (into [] (r/flatten coll)))