Reputation: 707
How could I convert this:
[a b c d e]
or this:
(e d c b a) ;(rseq [a b c d e])
to this:
[a[b[c[d[e]]]]]
I've been wracking my brain and I feel like there is a simple solution! :-\
Ultimately I want to do this:
[a b c d e]
[a b c x y]
[a b c d j k]
as this:
{a {b {c {d {e}
{j {k}}
{x {y}}}}
Which I think conj will help with
Upvotes: 1
Views: 117
Reputation: 84331
(Update: added answer to the new question added in the edit below the answer to the original question.)
I've actually answered this very question in #clojure recently.
Here are two approaches: f
is pretty much the spec directly transformed into code, which however creates a seq -- (next xs)
-- which immediately gets poured into a new vector at each step; g
is a much better version which only allocates objects which will actually occur in the output, plus a vector and the seq links to traverse it:
;; [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. I'm overlooking the usual logarithmic factors arising from vector operations (so this is soft-O complexity).
As for producing a nested map, the above isn't particularly useful. Here's one approach:
(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}}}}}
I'm using nil
as a "terminator", since {y}
(as currently found in the answer text) is not a well-formed literal. true
might be a more convenient choice if you plan to call these maps as functions to check for presence of keys.
Upvotes: 4
Reputation: 8128
Simpler solution here (using destructuring and non-tail recursion):
(defn wrap
([[a & as]]
(if-let [[b & cs] as]
[a (wrap as)]
[a])))
Upvotes: 4