On Dec 23, 6:04 am, Nicolas Buduroi <nbudu...@gmail.com> wrote:
> Hi, today I needed to use the map function on multiple collections
> which didn't had all the same length. In this case, it returns a
> sequence of the size of smallest one. But the problem I was facing was
> required to map until the end of the longest, padding the smaller ones
> with a default value. I came up with this:
>
> (defn mappad [f val & colls]
>   (let [longest (apply max (map count colls))
>         colls   (map #(if (< (count %) longest)
>                         (concat % (repeat val))
>                         %) colls)]
>     (apply (partial map f) colls)))
>
> user> (mappad #(+ %1 %2 %3) 0 [1] [2 3] [4 5 6])
> (7 8 6)
>
> Is there a better way?

Another, rather radical approach is to re-implement map with intrinsic
padding support (obviously based on clojure.core/map):

(defn map-longest
  "Returns a lazy sequence consisting of the result of applying f to
the
  set of first items of each coll, followed by applying f to the set
  of second items in each coll, until *all* of the colls are
exhausted.
  Missing items in exhausted colls are replaced with pad. Function
  f should accept number-of-colls arguments."
  ([f pad coll]
    (map f coll))
  ([f pad c1 c2]
   (lazy-seq
    (let [s1 (seq c1) s2 (seq c2)]
      (when (or s1 s2)
        (let [s1 (or s1 [pad])
              s2 (or s2 [pad])]
          (cons (f (first s1) (first s2))
                (map-longest f pad (rest s1) (rest s2))))))))
  ([f pad c1 c2 c3]
   (lazy-seq
    (let [s1 (seq c1) s2 (seq c2) s3 (seq c3)]
      (when (or s1 s2 s3)
        (let [s1 (or s1 [pad])
              s2 (or s2 [pad])
              s3 (or s3 [pad])]
          (cons (f (first s1) (first s2) (first s3))
                (map-longest f pad (rest s1) (rest s2) (rest
s3))))))))
  ([f pad c1 c2 c3 & colls]
   (let [step (fn step [cs]
                 (lazy-seq
                  (let [ss (map seq cs)]
                    (when (some identity ss)
                      (let [ss (reduce #(conj %1 (or %2 [pad])) []
ss)]
                        (cons (map first ss) (step (map rest
ss))))))))]
     (map #(apply f %) (step (conj colls c3 c2 c1))))))

Of course, this solution results in lots of code duplication, looks
rather unwieldy and is less general than Heinz' solution. I'm curious:
Does it have any merits that could make its use worthwhile?

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to