Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am interested in mapping a function, f over a (long) list which contains duplicates. Since this function takes a while to evaluate I would like to make use of this duplication to speed up the mapping.


Let us say my list is

list = {a, a, b, a, c, b}

my purpose is to map f over list efficiently. I have defined a function

MapDuplicate[f_, list_] := Module[{ff, list1, ulist},
list1 = ff /@ list; (* ff is dummy f *) 
ulist = Union[list]; (* the reduced list *)
rr = Dispatch[Thread[(ff /@ ulist) -> (f /@ ulist)]];
list1 /. rr]

which does the trick,

MapDuplicate[f1, list]

(* {f1(a),f1(a),f1(b),f1(a),f1(c),f1(b)} *)

but I strongly suspect there is a more elegant (using Ordering? SparseArray?) of doing this.


Any idea on how to do this more efficiently (e.g. without duplicating the list) My apologies in advance if the answer turns out to be trivial.

share|improve this question
Considered memoization? I.e., f[x_]:=f[x]= your definition used with Map: f/@list – kglr Aug 19 '12 at 13:03
No I had not! I tend to think of memorization as attached to the function rather than to lists. I guess it would do the trick. – chris Aug 19 '12 at 13:04
Though if I want to parallelize the mapping I suspect it won't work cf… – chris Aug 19 '12 at 13:07
Keep in mind that both memoization or other hash-based approaches (rules, Dispatch, etc) may actually make things slower for numerical lists when your function is compilable, since Map auto-compiles and switching to memoization etc you will lose that advantage (not to detract from the suggestions to use memoization etc, since those are the right things to do generically). – Leonid Shifrin Aug 19 '12 at 19:52
up vote 14 down vote accepted
dispatchTable = Dispatch[ # -> g[#] & /@ DeleteDuplicates[list]]
(* {a -> g[a], b -> g[b], c -> g[c]}  *)
(* {g[a], g[a], g[b], g[a], g[c], g[b]} *)

or memoization:

f[x_]:=f[x]= 3 x (* say *)

with Map

(*  {3 a, 3 a, 3 b, 3 a, 3 c, 3 b} *)

or with ParallelMap:

ParallelMap[f, list]  
share|improve this answer
it seems to me the last option, ParallelMap will not be as efficient as it should be because sub-kernels will not know about what other kernels have already memorized. – chris Aug 19 '12 at 13:16
@chris, good point. I have not done any testing with ParallelMap; and just saw your related question. Parallelization versus memoization (in case the choice is one of either/or) would make a great question: pros/cons, trade-offs involved etc. – kglr Aug 19 '12 at 13:23
I suggest modifying your answer to dispatchTable =Dispatch[ # -> g[#] & /@ DeleteDuplicates[list]] which will makes it more efficient if the dispatch table is long – chris Aug 19 '12 at 13:23
@chris, another great point. I actually did mean to use Dispatch:) – kglr Aug 19 '12 at 13:25
first option (dispatch) seems about 30 % faster. – chris Aug 19 '12 at 13:35

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.