在Clojure中顺序嵌套向量/列表?

时间:2013-07-11 17:03:04

标签: clojure

我怎么能转换它:

[a b c d e]

或者这个:

(e d c b a) ;(rseq [a b c d e])

到此:

[a[b[c[d[e]]]]]

我一直在绞尽脑汁,我觉得有一个简单的解决方案! : - \

最终我想这样做:

[a b c d e]
[a b c x y]
[a b c d j k]

这样:

{a {b {c {d {e}
            {j {k}}
         {x {y}}}}

我认为conj会帮助

2 个答案:

答案 0 :(得分:4)

(更新:在原始问题的答案下面的编辑中添加了新问题的答案。)

我最近在#clojure中回答了这个问题。

以下是两种方法:f几乎是直接转换为代码的规范,然而它会创建一个seq - (next xs) - 它会立即在每一步中涌入一个新的向量; g是一个更好的版本,它只分配实际出现在输出中的对象,加上一个向量和seq链接来遍历它:

;; [1 2 3] -> [1 [2 [3]]]

;; naive, quadratic:
(defn f [xs]
  (if (next xs)
    [(first xs) (vec (f (next xs)))]
    (vec xs)))

;; only allocates output + 1 vector + a linear number of seq links,
;; linear overall:
(defn g [v]
  (reduce (fn [acc x]
            [x acc])
          [(peek v)]
          (rseq (pop v))))

NB。我忽略了矢量运算产生的常用对数因子(所以这是soft-O复杂度。)


至于制作嵌套地图,以上并不是特别有用。这是一种方法:

(defn h
  ([v]
     (h nil v))
  ([m v]
     (assoc-in m v nil)))

(h [1 2 3 4])
;= {1 {2 {3 {4 nil}}}}

(def data
  '[[a b c d e]
    [a b c x y]
    [a b c d j k]])

(reduce h {} data)
;= {a {b {c {x {y nil}, d {j {k nil}, e nil}}}}}

我使用nil作为“终结者”,因为{y}(目前在答案文本中找到)不是格式正确的文字。如果您打算将这些地图称为检查是否存在密钥的函数,true可能是更方便的选择。

答案 1 :(得分:4)

这里更简单的解决方案(使用解构和非尾递归):

http://ideone.com/qchXZC

(defn wrap
  ([[a & as]]
    (if-let [[b & cs] as]
      [a (wrap as)]
    [a])))