简体   繁体   English

Clojure - 将函数应用于向量向量

[英]Clojure - Applying a Function to a vector of vectors

I have a vector [[[1 2] [3 4]] [[5 6] [7 8]] [9 10] 11] . 我有一个向量[[[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 every number but keep the data structure to get the result being [[[2 3] [4 5]] [[6 7] [8 9]] [10 11] 12] . 例如,我想为每个数字加1,但保持数据结构得到的结果是[[[2 3] [4 5]] [[6 7] [8 9]] [10 11] 12] Is this possible? 这可能吗?

I have 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. 但是你可以看到数据结构不一样。

Is there maybe a function that takes (2 3 4 5 6 7 8 9 10 11 12) to [[[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]

I thought maybe to use postwalk but I'm not sure if this is correct. 我想也许可以使用postwalk,但我不确定这是否正确。

Any help would be much appreciated 任何帮助将非常感激

You can use postwalk : 你可以使用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))

also the classic recursive solution is not much more difficult: 经典的递归解决方案也不难:

(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]]

Another way to solve your problem is via Specter . 解决问题的另一种方法是通过Spectre You do need another dependency then, but it can be a helpful 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 extend it to perform more complicated operations. 您可以扩展它以执行更复杂的操作。 For this use case normal Clojure is good enough. 对于这个用例,正常的Clojure就足够了。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM