idiom for padding sequences
Asked Answered
V

2

11

To pad out a sequence with some value, this is what I've come up with:

(defn pad [n coll val]
  (take n (concat coll (repeat val))))

(pad 10 [1 2 3] nil)   ; (1 2 3 nil nil nil nil nil nil nil)

I'm curious if there's a shorter idiom that does this already and perhaps more efficiently.

Visor answered 3/12, 2014 at 1:42 Comment(0)
T
11

Yes this is an idiomatic way of going about padding partitions of a sequence. In fact that code is very similar to part of the partition function in clojure.core the difference being that partition does not assume a single padding value and instead asks for a sequence:

core.clj:

([n step pad coll]
 (lazy-seq
    ...
    (list (take n (concat p pad))))))))

You can get the same results by passing a padding collection to partition:

user> (defn pad [n coll val]
        (take n (concat coll (repeat val))))
#'user/pad
user> (pad 10 [1 2 3] nil)
(1 2 3 nil nil nil nil nil nil nil)

user> (first (partition 10 10 (repeat nil) [1 2 3]))
(1 2 3 nil nil nil nil nil nil nil)
Tod answered 3/12, 2014 at 4:44 Comment(1)
Hmm, (first (partition n n (repeat pad) coll)) is actually slightly more verbose, and I doubt it performs better. It's having to unpack with first that bugs me. I was hoping for something really simple, like if take were to have an optional third pad arg: (take 5 (range 10) nil) => (0 1 2 3 4 nil nil nil nil nil) Oh well.Visor
L
0

Here's a lazy version of the padding function:

(defn lazy-pad
  "Returns a lazy sequence which pads sequence with pad-value."
  [sequence pad-value]
  (if (empty? sequence)
    (repeat pad-value)
    (lazy-seq (cons (first sequence) (lazy-pad (rest sequence) pad-value)))))

You can use it like a regular infinite lazy collection:

(take 5 (lazy-pad [1 2 3] :pad))
=> (1 2 3 :pad :pad)

IMO it's more elegant this way. You can also use it with other functions which expect a lazy sequence, which doesn't work if you have to specify the length upfront:

(partition 2 (interleave [1 2 3 4] (lazy-pad [:a] :pad)))
=> ((1 :a) (2 :pad) (3 :pad) (4 :pad))
Lazaro answered 17/7, 2017 at 12:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.