3
$\begingroup$

Recently, I have being using Mathematica to write my undergraduate paper. I want to use two pattern lists such as { A -> a, B -> b, c -> C, ....} and { a -> A, b -> B, c -> C, ....} to make my code short. I can exchange { A -> a, B -> b, c -> C, ....}'s elements to achieve { a -> A, b -> B, c -> C, ....}, my trail is as below:

firstPattern = { A -> a, B -> b, c -> C, one -> two, tom -> david};

To achieve { a -> A, b -> B, C -> c, two -> one, david -> tom}, I write the code:

{#1, #2} -> {#2, #1}& /@ firstPattern

However, it failed. I wonder why and how to correct it.

$\endgroup$
  • 1
    $\begingroup$ Is this what you intend? {#[[1]], #[[2]]} -> {#[[2]], #[[1]]} & /@ firstPattern $\endgroup$ – bill s May 2 '14 at 5:15
  • $\begingroup$ @bills,+1,OK,thanks sincerely,I achieve the right result $\endgroup$ – user9480 May 2 '14 at 5:21
  • 2
    $\begingroup$ It doesn't get simpler than Reverse /@ firstPattern :) $\endgroup$ – rm -rf May 2 '14 at 5:26
  • $\begingroup$ Somewhat related: (1302) $\endgroup$ – Mr.Wizard May 2 '14 at 5:34
7
$\begingroup$

Because life is more fun with infix:

firstPattern ~Reverse~ 2
{a -> A, b -> B, C -> c, two -> one, david -> tom}

(The serious point of this answer is that you can use the second parameter of Reverse to determine exactly what levels of the expression you wish to reverse.)

Also quite direct and terse:

#2 -> # & @@@ firstPattern
{a -> A, b -> B, C -> c, two -> one, david -> tom}

This works where your attempt doesn't by using Apply at level one, which has the shorthand @@@. This lets you access the parts of the rules rather than the entire rules themselves.


Timings

Timings, conducted in version 7, for various methods posted so far.

timeAvg = 
  Function[func,
    Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}],
    HoldFirst];

rules = Rule @@@ RandomInteger[999, {500000, 2}];

Reverse /@ rules     // timeAvg
Reverse[rules, 2]    // timeAvg
#2 -> # & @@@ rules  // timeAvg
rules[[All, {2, 1}]] // timeAvg
0.1934

0.1342

0.259

0.1902

In an attempt to make this answer more worthy of the Accept I'd like to arbitrarily address an edge case that might come up. Suppose you have RuleDelayed expressions and you wish to reverse them:

rules = {a :> 1 + 1, b :> 2 + 2, c :> 3 + 3};
rules ~Reverse~ 2
{2 :> a, 4 :> b, 6 :> c}

Note that e.g. 1 + 1 became 2; for the sake of the illustration let's consider this unacceptable. Then we would need to wrap the left-hand-side in HoldPattern. A direct attempt using @@@ fails because the anonymous Function does not hold its arguments (by default):

HoldPattern[#2] -> # & @@@ rules
{HoldPattern[2] -> a, HoldPattern[4] -> b, HoldPattern[6] -> c}

One could add a HoldAll Attribute to the function but usually replacement patterns are simpler:

Replace[rules, (L_ :> R_) :> (HoldPattern[R] :> L), 1]
{HoldPattern[1 + 1] :> a, HoldPattern[2 + 2] :> b, HoldPattern[3 + 3] :> c}

Such rules may seem pointless but they can be useful for manipulating held expressions.

$\endgroup$
  • $\begingroup$ @Mr.Wizard.Perfect! $\endgroup$ – user9480 May 2 '14 at 5:34
6
$\begingroup$

I always go with Part before attempting anything else:

firstPattern[[All, {2, 1}]]

To me at least it seems far simpler and more intuitive than many other approaches.

$\endgroup$
4
$\begingroup$

It doesn't get simpler than

Reverse /@ firstPattern

While Reverse is often used only on lists, it acts with any head, so Reverse@Rule[a, b] is Rule[b, a].

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy