Returns the result of applying concat to the result of applying map to f and colls. Thus function f should return a collection. Returns a transducer when no collections are provided
user=> (mapcat (fn [[k v]] (for [[k2 v2] v] (concat [k k2] v2))) '{:a {:x (1 2) :y (3 4)} :b {:x (1 2) :z (5 6)}}) ((:a :x 1 2) (:a :y 3 4) (:b :x 1 2) (:b :z 5 6))
user=> (require '[clojure.string :as cs]) nil ;; Suppose you have a fn in a `map` that itself returns ;; multiple values. user=> (map #(cs/split % #"\d") ["aa1bb" "cc2dd" "ee3ff"]) (["aa" "bb"] ["cc" "dd"] ["ee" "ff"]) ;; Now, if you want to concat them all together, you *could* ;; do this: user=> (apply concat (map #(cs/split % #"\d") ["aa1bb" "cc2dd" "ee3ff"])) ("aa" "bb" "cc" "dd" "ee" "ff") ;; But `mapcat` can save you a step: user=> (mapcat #(cs/split % #"\d") ["aa1bb" "cc2dd" "ee3ff"]) ("aa" "bb" "cc" "dd" "ee" "ff")
;; Suppose you've got a function that takes a value ;; and returns a list of things from it, for example: (defn f1 [n] [(- n 1) n (+ n 1)]) (f1 1) ;=> [0 1 2] ;; Perhaps you'd like to map it onto each item in a collection: (map f1 [1 2 3]) ;=> ([0 1 2] [1 2 3] [2 3 4]) ;; But suppose you wanted them all concatenated? You could do this: (apply concat (map f1 [1 2 3])) ;=> (0 1 2 1 2 3 2 3 4) ;; Or you could get the same thing with `mapcat`: (mapcat f1 [1 2 3]) ;=> (0 1 2 1 2 3 2 3 4)
; Flatten a map, consing keys on to each nested vector (mapcat (fn [[k vs]] (map (partial cons k) vs)) {:foo [[1 2] [3 2]] :bar [[3 1]]}) ;=> ((:foo 1 2) (:foo 3 2) (:bar 3 1))
;; A very useful feature of mapcat is that it allows function f to produce no result ;; by returning nil or an empty collection: (mapcat #(remove even? %) [[1 2] [2 2] [2 3]]) ;; => (1 3) ;; note that applying (remove even?) to [2 2] produced () which was "eaten" ;; and ignored by mapcat.
;; map vs. mapcat - ;; For duplicating each item in a sequence ;; Using map: (map #(repeat 2 %) [1 2]) ;; => ((1 1) (2 2)) ;; Using mapcat: (mapcat #(repeat 2 %) [1 2]) ;; => (1 1 2 2)
;; I think it is cool to use juxt together with mapcat ;; mapcat requires element to be collection and the result of juxt will be collection. (mapcat (juxt inc dec) [1 2 3 4]) ;; => (2 0 3 1 4 2 5 3)
Returns a lazy sequence consisting of the result of applying f to the set of first items of each c...
Returns a lazy seq representing the concatenation of the elements in the supplied colls.
Takes any nested combination of sequential things (lists, vectors, etc.) and returns their content...
;; mapcat always evaluates the first 4 arguments. (def a (mapcat range (map #(do (print ".") %) (into () (range 10))))) ;; .... ;; it can be solved avoiding 'apply' to handle varargs (defn mapcat* [f & colls] (letfn [(step [colls] (lazy-seq (when-first [c colls] (concat c (step (rest colls))))))] (step (apply map f colls)))) (def a (mapcat* range (map #(do (print ".") %) (into () (range 10))))) ;; nothing prints