Inverting replace direction

When we have a long list of rules it would be resonable choosing a functional approach, which is much faster than rule based one. In such cases consider e.g.

Reverse /@ rep

Sometimes it would be more efficient using Transpose twice than Map once, e.g.

Rule @@@ Transpose @ Reverse @ Transpose[ List @@@ rep]

Nonetheless ususally we need not to play with long lists and a simple pattern matching is quite sufficient, and so another approach might be e.g.

rep /. Rule[a_, b_] :> Rule[b, a]
 {b1 -> a1, b2 -> a2, b3 -> a3}

Mind using RuleDelayed in cases when it matters instead of Rule.


Part

Part is a general approach to this kind of reordering challenge:

rep = {a1 -> b1, a2 -> b2, a3 -> b3};

rep[[All, {2, 1}]]
{b1 -> a1, b2 -> a2, b3 -> a3}

Reference:

  • Head and everything except Head?

Reverse

Also there is a faster form of Reverse:

Reverse[rep, 2]
{b1 -> a1, b2 -> a2, b3 -> a3}

Slot / Function

Slot notation is compact though performance tends to be less than the options above:

#2 -> # & @@@ rep
{b1 -> a1, b2 -> a2, b3 -> a3}

Noteworthy is that unlike Part and Reverse this replaces heads. For example if you have a mixed list of Rule and RuleDelayed:

rep = {a1 -> b1, a2 :> b2, a3 -> b3};

#2 -> # & @@@ rep
rep[[All, {2, 1}]]
{b1 -> a1, b2 -> a2, b3 -> a3}

{b1 -> a1, b2 :> a2, b3 -> a3}

Performance

Comparative timings with a large list of rules:

rep =
  Rule @@@ RandomInteger[1*^7, {1*^6, 2}];

rep /. (x_ -> y_) :> (y -> x); // RepeatedTiming
#2 -> # & @@@ rep;             // RepeatedTiming
Reverse /@ rep;                // RepeatedTiming
rep[[All, {2, 1}]];            // RepeatedTiming
Reverse[rep, 2];               // RepeatedTiming
{0.62, Null}

{0.60, Null}

{0.475, Null}

{0.346, Null}

{0.334, Null}

{a1 -> b1, a2 -> b2, a3 -> b3}  /.  Rule[x_, y_] -> Rule[y, x]