5

How can I sort this in order from small to large? Simple Sort doesn't work here.

list={S1, S15, S19, S2, S26, S37, S50, S4, S8};
(*expectedOut={S1, S2, S4, S8, S15, S19, S26, S37, S50}*)
hana
  • 2,388
  • 5
  • 19

5 Answers5

10
SortBy[list, ToExpression[StringDrop[ToString[#], 1]] &]

Sort also work but needs longer code compared to previous one:

Sort[list, 
 ToExpression[StringDrop[ToString[#1], 1]] < 
   ToExpression[StringDrop[ToString[#2], 1]] &]

On the other hand if you used S[1] instead of S1... then simple Sort would be sufficient:

list = {S[1], S[15], S[19], S[2], S[26], S[37], S[50], S[4], S[8]};
Sort[list]

(* {S[1], S[2], S[4], S[8], S[15], S[19], S[26], S[37], S[50]} *)

Or if you used a more systematic names like S01 instead of S1... then also simple Sort would be sufficient:

list = {S01, S15, S19, S02, S26, S37, S50, S04, S08};
Sort[list]

(* {S01, S02, S04, S08, S15, S19, S26, S37, S50} *)

azerbajdzan
  • 15,863
  • 1
  • 16
  • 48
  • 1
    Also, indexed variables can be readily formatted in any desired format. For example, either Format[S[n_]] := "S" <> ToString[n] or Format[S[n_]] := Subscript[S, n] – Bob Hanlon Nov 10 '22 at 20:57
  • Numbers with filling zeros is nice too. Why does Sort work with S[1], S[2], etc? – hana Nov 10 '22 at 21:37
  • 5
    Could also do SortBy[list, Characters@*ToString] – chuy Nov 10 '22 at 22:37
  • 1
    @Chuy. Very nice. Perhaps you would consider posting as an answer? Users landing on this page looking for info may well be interested (and usually do not browse comments?). Also, list[[OrderingBy[list, Characters@*ToString]]] – user1066 Nov 11 '22 at 17:53
4
list = {S1, S15, S19, S2, S26, S37, S50, S4, S8};

ord = Ordering@(FromDigits@*ToExpression@*Rest@*Characters@*ToString /@
     list)
list[[ord]]

{S1, S2, S4, S8, S15, S19, S26, S37, S50}


For the case of leading zeros, the same solution applies:

list = {S1, S15, S19, S2, S26, S037, S50, S04, S008};

ord = Ordering@(FromDigits@ToExpression@Rest@Characters@ToString /@ list)

list[[ord]]

{S1, S2, S04, S008, S15, S19, S26, S037, S50}

Syed
  • 52,495
  • 4
  • 30
  • 85
3
list = {S100, S1, S15, S19, S2, S26, S37, S50, S4, S8};

Map[ToExpression @* StringJoin] @
 SortBy[Length] @
  Map[Characters @* ToString] @ list

{S1, S2, S4, S8, S15, S19, S26, S37, S50, S100}

eldo
  • 67,911
  • 5
  • 60
  • 168
1
list = {S100, S1, S15, S19, S2, S26, S37, S50, S4, S8};

A variant using SortBy:

ToExpression@*StringJoin @@@ 
Sort[Characters@*ToString /@ list /. v_ :> SplitBy[v, LetterQ]]

{S1, S2, S4, S8, S15, S19, S26, S37, S50, S100}

Also:

f = Symbol@*StringJoin @@@ Thread[{#[[All, 1]], Sort@#[[All, 2 ;;]]}] &;

f[Characters@*ToString /@ list]

{S1, S2, S4, S8, S15, S19, S26, S37, S50, S100}

E. Chan-López
  • 23,117
  • 3
  • 21
  • 44
1
num = ToExpression /@ 
  Flatten[StringCases[ToString /@ list, 
    "S" ~~ (x : DigitCharacter ..) -> x]]
list[[Ordering[num]]]

yields: {S1, S2, S4, S8, S15, S19, S26, S37, S50}

ubpdqn
  • 60,617
  • 3
  • 59
  • 148