# Is there a faster way to Map an Association?

Consider mapping an existing Association in a manner such as this:

asc = AssociationThread[Range @ 26, CharacterRange["a", "z"]];

Map[asc, {{11, 13, 2}, {19, 23, 16}}, {2}]

{{"k", "m", "b"}, {"s", "w", "p"}}


Is there a more efficient way perform this generic operation?

-
I guess I don't understand why I would want to Map an Association like that when the natural thing to use here is Replace or ReplaceAll. –  RunnyKine Jul 27 at 14:53
@RunnyKine You may already have an Association object to work with and converting to Rules and then Dispatch is slow (and pointless). In fact my experimentation indicates Association is faster than Dispatch in this application. –  Mr.Wizard Jul 27 at 15:02
@RunnyKine I updated my answer to highlight the fact that use of Association is not included in the documentation for Replace that I can see. –  Mr.Wizard Jul 27 at 15:03
Ah I see, I already knew they worked with Association objects, I thought I saw somewhere that almost all functions were updated to work with Associations so I just used them, didn't know this was not documented. Thanks. –  RunnyKine Jul 27 at 15:07
I see you're shooting for the Socratic badge ;) –  rm -rf Jul 27 at 15:17

Although apparently undocumented Replace and ReplaceAll work with Association and this combination is considerably faster than Map. Further it appears to be somewhat faster than using a Dispatch table as well.

Update: it seems Lookup is faster still. See additional timing result.

### Setup:

rules = Thread[Range @ 26 -> CharacterRange["a", "z"]];
asc   = <|rules|>;
d1    = Dispatch @ rules;
d2    = Dispatch @ asc;


Note another undocumented functionality: you can Dispatch an Association.

### Test:

{{11, 13, 2}, {19, 23, 16}} /. asc

Replace[{{11, 13, 2}, {19, 23, 16}}, asc, {2}]

{{"k", "m", "b"}, {"s", "w", "p"}}

{{"k", "m", "b"}, {"s", "w", "p"}}


### Timings:

time = Function[x, NumberForm[x // Timing // First // AbsoluteTiming, {4, 3}], HoldAll]

m = RandomInteger[{1, 26}, {2500, 2500}];

Map[asc, m, {2}]      // time
m /. asc              // time
Replace[m, asc, {2}]  // time
Replace[m, d1, {2}]   // time
Replace[m, d2, {2}]   // time

Lookup[asc, #] & /@ m // time

{1.318, 1.248}

{0.843, 0.827}

{0.477, 0.468}

{0.576, 0.562}

{0.576, 0.562}

{0.380, 0.359}


### Notes:

1. Replace at levelspec {2} is almost three times faster than the equivalent Map

2. ReplaceAll is not as fast but still faster than Map

3. The origin of the Dispatch` table appears to have no effect on performance

4. Although not included in the example relative timings hold with few or many rules

-