Search code examples
clojure

Using a mask vector to filter another vector


I have two vectors:

(def x [true false true]) 
(def y [1 2 3])

I'd like to filter y based on x. My initial attempt is like so:

(remove nil? (map #(when %1 %2) x y)) 

which returns (1, 3) as required.

My question is, is there a way I could have achieved the same result without having to filter out nils at the end? For example, I noticed keep removes nils before returning, but it doesn't seem to accept multiple collections, like map does. Is there a more elegant way of filtering using a mask vector like above?


Solution

  • A vector is an associative collection from indices to items at those indices, so I'd use reduce-kv:

    (reduce-kv (fn [result idx item]
                 (cond-> result (x idx) (conj item)))
               [] y)
    

    There's also keep-indexed that you can use as a transducer, but note that this approach will filter out any nils that might be present in the y vector:

    (into []
          (keep-indexed (fn [idx item]
                          (when (x idx) item)))
          y)