# How to sort subscripts of symbols in an expression?

For example, I want to change expr1 into expr2. I am pretty sure I can do this using nested loops to find and then modify terms with subscripts, but that is clunky, old school thinking. Is there a better way? "e" in my example below is a symbol (undefined).

(2 + Subscript[e, 2, 1] - Subscript[e, 3, 4, 5, 1, 2]) /.
Subscript[z1_, z2__] :> Subscript[z1, Sequence @@ Sort[List[z2]]]

(* 2 + Subscript[e, 1, 2] - Subscript[e, 1, 2, 3, 4, 5] *)


is one option.

• This is exactly the kind of solution I am looking for. Thank you so much. Now I'll try to digest how it works. I expect it will take me longer to digest it than it took you to produce it. – matrixbud Sep 30 '16 at 2:30
• I pretty much understand what you did and it is a very logical approach. I don't understand why a delayed rule rather than just a rule is needed, although I see that just a rule doesn't work at all. Is it difficult for you to explain what the delay does? – matrixbud Sep 30 '16 at 3:55
• @matrixbud Consider these simple cases. Subscript[e, 2, 1] /. Subscript[_, z2__] -> List[z2] gives {2, 1} for Rule or RuleDelayed, as it should. However, Subscript[e, 2, 1] /. Subscript[_, z2__] -> Sort[List[z2]] does not Sort, although RuldDelayed does. This is because the normal rule does the Sort on List[z2] before z2 is replaced by 2, 1. But, RuleDelayed does not do the Sort until after z2 is replaced by 2, 1. I hope this helps. – bbgodfrey Sep 30 '16 at 4:26
• Yes, that makes a lot of sense. To confirm that I understand how this works, I surmise that "List" is also delayed until after z2 is replaced, although that has no effect one way or the other on the final answer. That is, a delayed rule makes the direct substitution occur first and then all the subsequent operations (List and then Sort) happen after that. – matrixbud Sep 30 '16 at 14:53
• @matrixbud That is correct. f[2, 1] /. f[z__] -> {z} and f[2, 1] /. f[z__] :> {z} both give {{2, 1}, because delaying evaluation makes no difference. However, f[2, 1] /. f[z__] -> Sort[{z}] tries to Sort too soon and gives {2, 1}, while f[2, 1] /. f[z__] :> Sort[{z}] gives {1, 2}. – bbgodfrey Sep 30 '16 at 15:47