On Tue, Oct 09, 2012 at 15:31 -0700, Jean Niklas L'orange wrote: > On Tuesday, October 9, 2012 9:14:51 PM UTC+2, Wolodja Wentland wrote: > > --- snip --- > (reduce-kv > (fn [ret k v] > (assoc ret k (func-that-does-something-with v))) > some-map)) > --- snip -- > > I am using reducers in other places, but am not entirely sure how to > employ > them here. I would be grateful for any advice. > > You could use merge as the combine function, and let (fn [ret [k > v]] (assoc ret k (func-that-does-something-with v))) be the reducing > function you pass to fold. Then it's at least parallelisable, though I'm > unsure of its performance.
I played with the following implementation:
(defn update-vals
[m f]
(persistent!
(reduce-kv
(fn [ret k v]
(assoc! ret k (f v)))
(transient {})
m)))
(defn pupdate-vals
[m f]
(r/fold
(r/monoid merge hash-map)
(fn [ret [k v]]
(conj ret [k (f v)]))
(vec m)))
(defn foo
[x]
(Thread/sleep 0.2)
(inc x))
but unfortunately update-vals still outperforms pupdate-vals even on large
maps. I am not sure what else I can do to speed up folding into maps
(as opposed to a single value), but I'll keep on experimenting.
user=> (def m (zipmap (range 100000) (range 100000)))
#'user/m
user=> (time (dotimes [_ 100] (pupdate-vals m inc)))
"Elapsed time: 8068.950282 msecs"
nil
user=> (time (dotimes [_ 100] (update-vals m inc)))
"Elapsed time: 1106.253256 msecs"
nil
user=> (time (dotimes [_ 100] (pupdate-vals m foo)))
"Elapsed time: 8890.445481 msecs"
nil
user=> (time (dotimes [_ 100] (update-vals m foo)))
"Elapsed time: 3954.917294 msecs"
--
Wolodja <[email protected]>
4096R/CAF14EFC
081C B7CD FF04 2BA9 94EA 36B2 8B7F 7D30 CAF1 4EFC
signature.asc
Description: Digital signature
