Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nested maps to nested vectors in clojure

Tags:

clojure

I was wondering what the most idiomatic way would be in clojure to transform a nested map to a nested vector.

For example from:

{:left {:left {:left 1, :right 5, :middle 1, :score 10}, :right {:left 7, :right 8, :middle 7, :score 0}, :middle 5, :score 10}, :right 9, :middle 8, :score 10}

to:

[ [ [ 1,  5, 1, 10 ],  [ 7, 8, 7, 0], 5, 10], 9, 8, 10]

Many thanks

like image 308
user1782011 Avatar asked Mar 23 '14 09:03

user1782011


2 Answers

You can use clojure.walk/postwalk to traverse Clojure data structures in post-order (i.e. start at the leaves) and replace the maps with a vector of [:left :right :middle :score] values:

(require '[clojure.walk :refer [postwalk]])

(def nested-map 
  {:left {:left {:left 1, :right 5, :middle 1, :score 10}, 
          :right {:left 7, :right 8, :middle 7, :score 0}, 
          :middle 5, 
          :score 10}, 
   :right 9, 
   :middle 8, 
   :score 10})

(postwalk
  (fn [v]
    (if (map? v)
      ((juxt :left :right :middle :score) v)
      v))
  nested-map)
;; => [[[1 5 1 10] [7 8 7 0] 5 10] 9 8 10]
like image 178
xsc Avatar answered Sep 19 '22 14:09

xsc


My shot at it:

(clojure.walk/postwalk #(if (map? %) (into [] (vals %)) %) nested-map)
=> [[5 10 [7 0 8 7] [1 10 5 1]] 8 9 10]

It doesn't preserve order when used with hash-maps; it will however, preserve order with array-maps.

like image 5
deadghost Avatar answered Sep 22 '22 14:09

deadghost