# Swap two numbers - but only in a particular context

I have a list of terms such as {2*s[1,2]^2, 3*s[3,5]^4, ...} and I would like to have a replacement that swaps $$2 \leftrightarrow 4, 3 \leftrightarrow 1$$, but only within the s[i,j] objects. The first guess:

In:= {2*s[1,2]^2,3*s[3,5]^4} /. {2:>4, 4:>2, 3:>1, 1:>3}
Out= {4 s[3,4]^4,s[1,5]^2}


does not work as it also changes the prefactors and powers. Because of the vast number of elements in the list (and the fact that I can also have more than two arguments, e.g. s[1,2,3], s[1,2,3,4], ...), it's impractical to manually code in each s[1,2]:>s[3,4] and so on. How would I write a replacement with a condition that it affects numbers only within s[i,j]?

• Can s have something else than an integer as an argument? E.g. s[ 1, s[2, a^2] ]? – Kuba Jul 10 '20 at 11:26
• No, it's just numbers like s[1,2], s[1,2,3],... – dzejkob Jul 10 '20 at 11:31

## 2 Answers

One way:

list = {2*s[1, 2]^2, 3*s[3, 5]^4, g[s[3, 4, 0, 2]]};

list /. expr : s[__] :> (expr /. {
1 -> 2,
2 -> 20,
3 -> 4,
4 -> 40,
5 -> 50
})


{2 s[2, 20]^2, 3 s[4, 50]^4, g[s[4, 40, 0, 20]]}

Not sure this is a slick solution but seems to work:

rules = {2 <-> 4, 3 <-> 1} /. {a_ <-> b_ :> {a -> b, b -> a}} //
Flatten;
{2*s[1, 2]^2, 3*s[3, 5]^4} /. p : s[_, _] :> (p /. rules)