(mapcat f) (mapcat f & colls)
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 reverse [[3 2 1 0] [6 5 4] [9 8 7]])
(0 1 2 3 4 5 6 7 8 9)
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)