在clojure中使用具有不同大小集合的"map"

use*_*655 7 collections functional-programming clojure map

我想了解在clojure中对不同大小的集合进行操作的惯用方法.有没有办法告诉函数'map'用一些默认值填充集合的其余部分?

举个例子,假设我有3个向量:

(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)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如何用零填充x和y并获得此收益:

(3 6 9 12 10 6 7)
Run Code Online (Sandbox Code Playgroud)

jbm*_*jbm 12

map不这样做本身,而是你可以使用的组合concat,并repeat获得期望的结果:

(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)
Run Code Online (Sandbox Code Playgroud)

这是concat重复的API文档.

这里有一个草图,说明如何将它抽象出来,所以你不需要知道哪个集合最长.(在上面的代码片段中,如果你concat所有的集合(repeat 0)都有无限的序列).

(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)
Run Code Online (Sandbox Code Playgroud)

您可以在Stack Overflow上看到其他几种方法作为上一个问题的答案.