2
$\begingroup$

I have a large list of codes of the following form:

codes = {"Fee.C21HJ.S4", "Fee.TOxC12.S1", "Fee.TOxC9.2 BB", "Fee.ROxC9.4", "Lag.C39"};

I would like to sort codes of this form by their alpha and numeric tokens.

What I mean by "alpha and numeric tokens" are any runs of DigitCharacter or LetterCharacter in the code.

For codes (with NumberStrings converted numbers) this would give

tokens = StringCases[{Longest[LetterCharacter ..], 
    n : Longest[DigitCharacter ..] :> FromDigits[n]}] /@ codes
{{"Fee", "C", 21, "HJ", "S", 4}, 
 {"Fee", "TOxC", 12, "S", 1}, 
 {"Fee", "TOxC", 9, 2, "BB"}, 
 {"Fee", "ROxC", 9, 4}, 
 {"Lag", "C", 39}}

The codes sorted by each column in turn would give

sorted = {"Fee.C21HJ.S4", "Fee.ROxC9.4", "Fee.TOxC9.2 BB", "Fee.TOxC12.S1", "Lag.C39"}

Notice that the code token lengths are different and it is possible for a code to be sorted before another code that has a shorter token length.

Ordering does not work as it considers the length of the token lists first. It would place "Lag.C39" as the first code when it should be the last.

How to sort alphanumeric codes by their alpha and numeric tokens?

$\endgroup$
2
$\begingroup$

Can you just use PadRight followed by Ordering?

codes = {"Fee.C21HJ.S4", "Fee.TOxC12.S1", "Fee.TOxC9.2 BB", "Fee.ROxC9.4", "Lag.C39"};

tokens = StringCases[{
    Longest[LetterCharacter ..],
    n : Longest[DigitCharacter ..] :> FromDigits[n]
}] /@ codes;

codes[[Ordering @ PadRight[tokens, Automatic, Infinity]]]

{"Fee.C21HJ.S4", "Fee.ROxC9.4", "Fee.TOxC9.2 BB", "Fee.TOxC12.S1", "Lag.C39"}

$\endgroup$
  • $\begingroup$ Nice one.. beat me by 30 seconds. $\endgroup$ – halirutan Jan 4 '18 at 16:11

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.