7
$\begingroup$

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?

$\endgroup$
9
  • $\begingroup$ 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. $\endgroup$
    – RunnyKine
    Jul 27, 2014 at 14:53
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Jul 27, 2014 at 15:02
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Jul 27, 2014 at 15:03
  • $\begingroup$ 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. $\endgroup$
    – RunnyKine
    Jul 27, 2014 at 15:07
  • $\begingroup$ I see you're shooting for the Socratic badge ;) $\endgroup$
    – rm -rf
    Jul 27, 2014 at 15:17

1 Answer 1

11
$\begingroup$

Although announced for 10.0.2 the functionality below works from 10.0.0 onward.


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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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