Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add element to vector in nested tree structure

Tags:

clojure

Jumping right in, better way of doing this:

(assoc-in 
    {:children [{:children [{:children [{:children [{:children []}]}]}]}]} 
    [:children 0 :children 0 :children 0 :children 0 :children 0] 
    :hello)

I want to insert :hello into deepest :children vector. Above I am doing it with assoc-in.

Is there a better way than assoc-in?
Or, if when assoc-in is the only way, how would you handle assoc-in's 2nd argument [k & ks]?

Also good to know if there it something that also works for inserting :world into and arbitrary :children's vector... like the 3rd child or the 2nd child's 1st child.

like image 624
Ross Avatar asked Apr 10 '14 20:04

Ross


People also ask

Can we add an element in the middle in vector?

Elements can be added in the middle of a Vector by using the java. util. Vector. insertElementAt() method.

How do you add an element to a vector?

To add elements to vector, you can use push_back() function. push_back() function adds the element at the end of this vector. Thus, it increases the size of vector by one.

How do you add an element to an array in vector?

Insertion: Insertion in array of vectors is done using push_back() function. Above pseudo-code inserts element 35 at every index of vector <int> A[n]. Traversal: Traversal in an array of vectors is perform using iterators.

Can you add elements to the front of an STL vector?

vector insert() function in C++ STL std::vector::insert() is a built-in function in C++ STL which inserts new elements before the element at the specified position, effectively increasing the container size by the number of elements inserted.


1 Answers

The vector argument to assoc-in need not be a literal, so you can construct it as desired.

(def nested-map  
  {:children [{:children [{:children [{:children [{:children []}]}]}]}]})

(assoc-in nested-map (vec (take 10 (cycle [:children 0]))) :hello)
;=> {:children [{:children [{:children [{:children [{:children [:hello]}]}]}]}]}

Or for 3rd child of the 2nd child of the 1st child, construct a path like

(vec (interleave (repeat :children) [0 1 2]))
;=> [:children 0 :children 1 :children 2]

More generally you can use zippers to arbitrarily move around the nested map, e.g. descend last child. The movement functions are can be composed, etc.

(require '[clojure.zip :as zip])

(def z (zip/zipper map? :children #(assoc % :children (vec %2)) nested-map))

(-> (ffirst (filter (comp zip/end? second)  ; find last
                    (partition 2 1 (iterate zip/next z)))) 
    (zip/edit (constantly :hello)) ; change to :hello
    zip/root) ; bubble up changes

;=> {:children [{:children [{:children [{:children [{:children [:hello]}]}]}]}]}
like image 166
A. Webb Avatar answered Sep 21 '22 20:09

A. Webb