7
$\begingroup$

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!

$\endgroup$

4 Answers 4

9
$\begingroup$

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)] 
$\endgroup$
6
  • $\begingroup$ Another way to generate the replacement rules: Dispatch[Apply[Join, Thread[# -> Reverse[#]] & /@ pairs]]. $\endgroup$ Commented Aug 26, 2012 at 11:21
  • $\begingroup$ @J.M. really nice. More concise than everything I have tried. $\endgroup$ Commented Aug 26, 2012 at 12:33
  • $\begingroup$ @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.) $\endgroup$ Commented Aug 26, 2012 at 13:24
  • 1
    $\begingroup$ @Noble P. Abraham That's probably because I asked for the original matrix to be replaced in my question. $\endgroup$ Commented Aug 26, 2012 at 13:36
  • 2
    $\begingroup$ @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. $\endgroup$ Commented Aug 26, 2012 at 13:53
11
$\begingroup$

ReplaceAll should do it:

{{2, 4, 1}, {3, 1, 2}, {4, 3, 1}} /. {2 -> 3, 3 -> 2} 
$\endgroup$
0
4
$\begingroup$

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] 
$\endgroup$
3
$\begingroup$

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}} *) 
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.