Using 'map' with different sized collections in clojure

落花浮王杯 提交于 2019-12-22 05:01:01

问题


I'd like to understand the idiomatic way with which to operate over collections of different sizes in clojure. Is there a way I can tell the function 'map' to pad the rest of a collection with some default value?

As an example, suppose I have 3 vectors:

(def x [1 2 3 4])
(def y [1 2 3 4 5])
(def z [1 2 3 4 5 6 7])

(map + x y z)    ; yields (3 6 9 12)

In this case, how can I pad x and y with zeroes and have this yield:

(3 6 9 12 10 6 7)

回答1:


map doesn't do it itself, but you can use a combination of concat and repeat to obtain the desired result:

(def x [1 2 3 4])
(def y [1 2 3 4 5])
(def z [1 2 3 4 5 6 7])

(map +
     (concat x (repeat 0))
     (concat y (repeat 0))
     z) ; => (3 6 9 12 10 6 7)

Here's the API documentation for concat, and for repeat.

And here's a sketch of how you could abstract this away a bit, so you don't need to know which of the collections is longest. (In the snippet above, if you concat all the collections to (repeat 0) you'll have an infinite sequence).

(defn map-longest
  [f default & colls]
  (lazy-seq
   (when (some seq colls)
     (cons
      (apply f (map #(if (seq %) (first %) default) colls))
      (apply map-longest f default (map rest colls))))))

(map-longest +
             0
             [1 2 3 4]
             [1 2 3 4 5]
             [1 2 3 4 5 6 7]) ; => (3 6 9 12 10 6 7)

You can see a couple other approaches as answers to this previous question on Stack Overflow.




回答2:


You can merge vector of maps with variable lengths by the following function:

(defn merge-maps
  [& args]
  (let [max-count (apply max (map #(count %1) args))
        items (map #(take max-count (concat %1 (repeat nil))) args)]
    (apply map merge items)))

This function makes the solution more generalized and can take any length of vector of maps.



来源:https://stackoverflow.com/questions/18940629/using-map-with-different-sized-collections-in-clojure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!