Clojure map-longest

Here is a solution:

(defn map-longest
  ([fn missing-value-fn c1]
    (map fn c1))
  ([fn missing-value-fn c1 & colls]
    (lazy-seq
      (when (not-every? empty? (conj colls c1))
        (let [firsts (map first (conj colls c1))]
          (cons
            (apply fn (map #(if (nil? %) (missing-value-fn) %) firsts))
            (apply map-longest
              (conj (map rest colls) (rest c1) missing-value-fn fn))))))))

Test:

user=> (print (apply str 
         (map-longest #(str %1 \space %2 \space %3 \newline) #(identity "--") 
           ["a1" "a2" "a3"] ["b1" "b2"] ["c1" "c2" "c3" "c4"])))
a1 b1 c1
a2 b2 c2
a3 -- c3
-- -- c4
nil

Note that I have taken the missing-value-fn approach rather than the missing-value-seq one.

Update

Updated the code to take care of the case mentioned by ffriend in the comments.

Test:

user=> (print (apply str
          (map-longest #(str %1 \space %2 \space %3 \newline) #(identity "--")
            ["a1" "a2" nil] ["b1" "b2"] ["c1" "c2" nil "c4"])))
a1 b1 c1
a2 b2 c2
-- -- --
-- -- c4
nil

Please note that this will replace nils in the colls with the value returned by the missing-value-fn.

Tags:

Clojure

Map