我想了解在 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)
在这种情况下,我如何用零填充 x 和 y 并获得以下收益:
(3 6 9 12 10 6 7)
我想了解在 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)
在这种情况下,我如何用零填充 x 和 y 并获得以下收益:
(3 6 9 12 10 6 7)
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)
这是一个关于如何将其抽象出来的草图,因此您无需知道哪个集合最长。(在上面的代码片段中,如果您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)
您可以在 Stack Overflow 上看到其他几种方法作为对上一个问题的答案。
您可以通过以下函数合并具有可变长度的地图矢量:
(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)))
此功能使解决方案更加通用,并且可以采用任意长度的地图矢量。