【问题标题】:Using 'map' with different sized collections in clojure在 clojure 中使用具有不同大小集合的'map'
【发布时间】:2013-09-27 06:00:16
【问题描述】:

我想了解在 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)

【问题讨论】:

    标签: collections map clojure functional-programming


    【解决方案1】:

    map 不会自己做,但是你可以使用concatrepeat 的组合来获得想要的结果:

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

    这是concatrepeat 的 API 文档。

    这里有一个关于如何将其抽象出来的草图,因此您无需知道哪个集合最长。 (在上面的sn-p中,如果你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)
    

    您可以看到其他几种方法作为this previous question on Stack Overflow 的答案。

    【讨论】:

      【解决方案2】:

      您可以通过以下函数合并可变长度的地图矢量:

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

      这个函数使解更加泛化,可以取任意长度的地图向量。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多