Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Is there a nice, simple script one can use to swap two entires in a matrix? For example, suppose we have the matrix below:

$A=\begin{pmatrix}2 & 4 & 1\\ 3 & 1 & 2\\ 4 & 3 & 1 \end{pmatrix}$

Is there a script of the form switch[A,a,b], which will swap all occurrences of $a$ in the matrix with $b$, and vice versa, and then update the matrix $A$ accordingly? So in this case the output of switch[A,2,3] would be:

$A=\begin{pmatrix}3 & 4 & 1\\ 2 & 1 & 3\\ 4 & 2 & 1 \end{pmatrix}$

My own solution involves a lot of If and For functions, and will, I think, also run into the problems detailed here. I think it will work eventually (and I'd be happy to post what I have so far if people would like), but really I'm just wondering whether there's a simpler way to do this.

Thanks!

share|improve this question
add comment

4 Answers 4

up vote 8 down vote accepted

A minor point regarding ReplaceAll: ReplaceAll does not change the matrix a, so you do need to set a= (a/. {replacement rules}) or a=ReplaceAll[a,{replacement rules}].

 a = {{2, 4, 1}, {3, 1, 2}, {4, 3, 1}};
 a = (a /. {2 -> 3, 3 -> 2});
 a // MatrixForm

enter image description here

Another alternative is to use Replace at level 2:

 a = Replace[a, {2 -> 3, 3 -> 2}, {2}] 

or at level -1:

 a = Replace[a, {2 -> 3, 3 -> 2}, {-1}] 

Yet another alternative:

 a = Cases[a, {x___, aa : (3 | 2), y___} :> {x, If[aa == 3, 2, 3], y}, {1,Infinity}]

Update: functions to swap a pair of elements of a matrix:

ClearAll[swap];
SetAttributes[swap, HoldFirst];
swap[mat_, elem1_, elem2_] := (mat = mat /. {elem1 -> elem2, elem2 -> elem1})
swap[a,2,3]
 (* {{3, 4, 1}, {2, 1, 3}, {4, 2, 1}} *)

Swap multiple pairs of elements:

ClearAll[swap2];
SetAttributes[swap2, HoldFirst];
swap2[mat_, pairs:{{_, _} ..}] := (mat = mat /.(Rule @@@ Join[pairs, Reverse /@ pairs]))
swap2[a,{{2,3}}]
 (* {{2, 4, 1}, {3, 1, 2}, {4, 3, 1}}  *)
swap2[a,{{2,3},{1,4}}]
 (* {{3, 1, 4}, {2, 4, 3}, {1, 2, 4}} *)

For large matrices and many pairs to swap:

ClearAll[swap3];
SetAttributes[swap3, HoldFirst];
swap3[mat_, pairs : {{_, _} ..}] :=  With[{dispatch = Dispatch[Rule @@@ Join[pairs, Reverse /@ pairs]]}, mat = (mat /. dispatch)]
share|improve this answer
    
Another way to generate the replacement rules: Dispatch[Apply[Join, Thread[# -> Reverse[#]] & /@ pairs]]. –  J. M. Aug 26 '12 at 11:21
    
@J.M. really nice. More concise than everything I have tried. –  kguler Aug 26 '12 at 12:33
    
@kguler Won't it be better if the swap function do not replace the original matrix itself? (I mean, if both a and swapped a are needed.) –  Noble P. Abraham Aug 26 '12 at 13:24
1  
@Noble P. Abraham That's probably because I asked for the original matrix to be replaced in my question. –  Jimeree Aug 26 '12 at 13:36
2  
@NobleP.Abraham, I agree with you. To get a version that does not replace the input matrix, one can remove the part mat= in the definition of swap and use a=swap[a,...] when one needs to replace a. –  kguler Aug 26 '12 at 13:53
show 1 more comment

ReplaceAll should do it:

{{2, 4, 1}, {3, 1, 2}, {4, 3, 1}} /. {2 -> 3, 3 -> 2}
share|improve this answer
add comment

With ReplacePart and Position:

a = {{2, 4, 1}, {3, 1, 2}, {4, 3, 1}};
ReplacePart[a, {Position[a, 2] -> 3, Position[a, 3] -> 2}]

(* {{3, 4, 1}, {2, 1, 3}, {4, 2, 1}} *)
share|improve this answer
add comment

I like the above ReplaceAll solution the most. But to make sure there are at least 10 different ways to do something in Mathematica, here is another way

mat = {{2, 4, 1}, {3, 1, 2}, {4, 3, 1}};
pos1 = Position[mat, 2];
pos2 = Position[mat, 3];
mat = ReplacePart[mat, pos1 -> 3];
mat = ReplacePart[mat, pos2 -> 2]
share|improve this answer
add comment

Your Answer

 
discard

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.