Clojure - Applying a function to a vector of vectors

I have a vector [[[1 2] [3 4]] [[5 6] [7 8]] [9 10] 11] . I want to apply a function to this vector, but keep the data structure.

For example, I want to add 1 to each number, but save the data structure to get the result [[[2 3] [4 5]] [[6 7] [8 9]] [10 11] 12] . Is it possible?

I tried

 (map #(+ 1 %) (flatten [[[1 2] [3 4]] [[5 6] [7 8]] [9 10] 11])) => (2 3 4 5 6 7 8 9 10 11 12) 

But you can see that the data structure is not the same.

Perhaps there is a function that takes from (2 3 4 5 6 7 8 9 10 11 12) to [[[2 3] [4 5]] [[6 7] [8 9]] [10 11] 12]

I thought it might be possible to use postwalk, but I'm not sure if this is correct.

Any help would be greatly appreciated

+5
source share
3 answers

You can use postwalk :

 (require '[clojure.walk :as walk]) (let [t [[[1 2] [3 4]] [[5 6] [7 8]] [9 10] 11]] (walk/postwalk (fn [x] (if (number? x) (inc x) x)) t)) 
+6
source

also the classic recursive solution is not much more complicated:

 (defn inc-rec [data] (mapv #((if (vector? %) inc-rec inc) %) data)) #'user/inc-rec user> (inc-rec [1 [2 3 [4 5] [6 7]] [[8 9] 10]]) ;;=> [2 [3 4 [5 6] [7 8]] [[9 10] 11]] 
+4
source

Another way to solve your problem is Specter . Then you need another dependency, but it could be a useful library.

 (ns your-ns.core (:require [com.rpl.specter :as specter])) (def data [[[1 2] [3 4]] [[5 6] [7 8]] [9 10] 11]) (specter/defprotocolpath TreeWalker) ;; define path walker (specter/extend-protocolpath TreeWalker ;; stop walking on leafs (in this case long) Object nil ;; when we are dealing with a vector, TreeWalk all elements clojure.lang.PersistentVector [specter/ALL TreeWalker]) 

You can expand it to perform more complex operations. For this use case, normal Clojure is good enough.

 (specter/transform [TreeWalker] inc data) ;; => [[[2 3] [4 5]] [[6 7] [8 9]] [10 11] 12] 
0
source

Source: https://habr.com/ru/post/1269828/


All Articles