# Sorting alphanumeric strings

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]...

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

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"} *)


Narrow but FWIW:

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


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"}


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.