我有一个向量[[[1 2] [3 4]] [[5 6] [7 8]] [9 10] 11]
。我想将一个函数应用于此向量,但保留数据结构。
例如,我想为每个数字添加1,但保留数据结构以使结果为[[[2 3] [4 5]] [[6 7] [8 9]] [10 11] 12]
。这可能吗?
我试过了
(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)
但是你可以看到数据结构不一样。
是否有一个功能需要(2 3 4 5 6 7 8 9 10 11 12)
到[[[2 3] [4 5]] [[6 7] [8 9]] [10 11] 12]
我想也许可以使用postwalk,但我不确定这是否正确。
非常感谢任何帮助
答案 0 :(得分:6)
您可以使用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))
答案 1 :(得分:4)
经典的递归解决方案也不难:
(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]]
答案 2 :(得分:0)
解决问题的另一种方法是通过Specter。您确实需要另一个依赖项,但它可以是一个有用的库。
(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])
您可以对其进行扩展以执行更复杂的操作。对于这个用例,正常的Clojure就足够了。
(specter/transform [TreeWalker] inc data)
;; => [[[2 3] [4 5]] [[6 7] [8 9]] [10 11] 12]