1
$\begingroup$

Say I have

strings = {"a16", "b22", "a8", "c1", "b18", "b2", "a1"};

Sort@strings gives {"a1", "a16", "a8", "b18", "b2", "b22", "c1"}, but I'd like to obtain {"a1", "a8", "a16", "b2", "b18", "b22", "c1"}. What's the shortes and most elegant way to do so? It could be done with StringSplit, ToExpression, Ordering etc., but this all looks like an exaggeration; I expected MMA to have something like SortBy[strings,AlphaNumericalOrder]...

$\endgroup$
  • $\begingroup$ Perhaps this works: SortBy[strings, Characters]. Edit: it doesn't. $\endgroup$ – march Oct 11 '16 at 23:29
  • $\begingroup$ @march It works for cases when all strings in strings start with the same letter, e.g. a. $\endgroup$ – corey979 Oct 12 '16 at 7:50
2
$\begingroup$

If we define:

alphanumeric = StringReplace[d:DigitCharacter.. :> FromDigits[d]];

then we can write:

alphanumeric["a16"]

(* "a" ~~ 16 *)

and thus:

SortBy[strings, alphanumeric]

(* {"a1", "a8", "a16", "b2", "b18", "b22", "c1"} *)
$\endgroup$
3
$\begingroup$

Narrow but FWIW:

strings[[Ordering[(Characters /@ 
      strings) /. {{x_, y_} :> {x, 0, y}}]]]
$\endgroup$
2
$\begingroup$

Not too elegant, but SortBy[] with two custom tie-breaking functions does the job:

SortBy[strings, {First[StringCases[#, LetterCharacter ..]] &, 
                 FromDigits[First[StringCases[#, DigitCharacter ..]]] &}]
   {"a1", "a8", "a16", "b2", "b18", "b22", "c1"}
$\endgroup$
1
$\begingroup$

A hokey way to do it would be to add a zero before the single digits.

Start by defining a simple function:

f = StringReplace[#, (x : LetterCharacter ~~ y : DigitCharacter ~~ 
      EndOfString) :> x <> "0" <> y] &

Then

SortBy[strings, f]

{"a1", "a8", "a16", "b2", "b18", "b22", "c1"}

This naturally would have to be expanded for strings in which the digits are larger than 100.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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