I tried keeping your approach, although I would've made it an infinite lazy sequence. Yours is probably a better idea, since you still have the infinite sequence (mapping to range as you did) and you can map it to other non-linear sequences too.
(def targets ;; This is more readable for me
(sorted-map
3 "fizz",
5 "buzz",
7 "baz"))
(defn fizzbuzz [targets n] ;; Pass the targets here! Commas aren't very common in args lists
(let [matches (keep (fn [[f w]] ;; Destructuring is nice :P
(when (zero? (mod n f)) w)) ;; Got rid of your helper function
targets)] ;; ^ Use 'zero?' instead of '(= 0 ...)'
(if (empty? matches) ;; Use 'empty?' instead of '(= 0 (count ...))'
(str n)
(apply str matches)))) ;; I prefer apply here, but seen both
;;;;; EXAMPLE
(map (partial fizzbuzz targets) (range 1 20))
=> ("1" "2" "fizz" "4" "buzz" "fizz" "baz" "8" "fizz" "buzz" "11" "fizz" "13" "baz" "fizzbuzz" "16" "17" "fizz" "19" "buzz")
There's an even more idiomatic way to rewrite the (if (empty? matches)...)
bit:
(if matches
(apply str matches)
(str n))
Lazy sequence style. Consider fizzbuzz and targets are already defined:
(defn lazy-fizzbuzz
([targets n]
(lazy-seq
(cons (fizzbuzz targets n)
(lazy-fizzbuzz targets (inc n)))))
([targets]
(lazy-fizzbuzz targets 1)))
;;;;; EXAMPLES
(take 20 (lazy-fizzbuzz targets))
=> ("1" "2" "fizz" "4" "buzz" "fizz" "baz" "8" "fizz" "buzz" "11" "fizz" "13" "baz" "fizzbuzz" "16" "17" "fizz" "19" "buzz")
;; You can also specify an initial n
(take 20 (lazy-fizzbuzz targets 20))
=> ("buzz" "fizzbaz" "22" "23" "fizz" "buzz" "26" "fizz" "baz" "29" "fizzbuzz" "31" "32" "fizz" "34" "buzzbaz" "fizz" "37" "38" "fizz")
;; which is the same as...
(take 20 (drop 19 (lazy-fizzbuzz targets)))
=> ("buzz" "fizzbaz" "22" "23" "fizz" "buzz" "26" "fizz" "baz" "29" "fizzbuzz" "31" "32" "fizz" "34" "buzzbaz" "fizz" "37" "38" "fizz")