5
$\begingroup$

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

5 Answers 5

10
$\begingroup$
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} *)
$\endgroup$
4
  • 1
    $\begingroup$ 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] $\endgroup$
    – Bob Hanlon
    Commented Nov 10, 2022 at 20:57
  • $\begingroup$ Numbers with filling zeros is nice too. Why does Sort work with S[1], S[2], etc? $\endgroup$
    – hana
    Commented Nov 10, 2022 at 21:37
  • 5
    $\begingroup$ Could also do SortBy[list, Characters@*ToString] $\endgroup$
    – chuy
    Commented Nov 10, 2022 at 22:37
  • 1
    $\begingroup$ @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]]] $\endgroup$
    – user1066
    Commented Nov 11, 2022 at 17:53
4
$\begingroup$
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}

$\endgroup$
4
$\begingroup$
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}

$\endgroup$
2
$\begingroup$
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}

$\endgroup$
2
$\begingroup$
num = ToExpression /@ 
  Flatten[StringCases[ToString /@ list, 
    "S" ~~ (x : DigitCharacter ..) -> x]]
list[[Ordering[num]]]

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.