(更新:元の質問への回答の下の編集で追加された新しい質問への回答を追加しました。)
私は最近 #clojure でまさにこの質問に答えました。
ここに 2 つのアプローチが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))))
注意。ベクトル演算から生じる通常の対数係数を見落としています (したがって、これはソフト O の複雑さです)。
ネストされたマップの作成に関しては、上記は特に役に立ちません。1 つのアプローチを次に示します。
(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