This is the routine I use to sort LC call numbers. The regex breaks the call number into it's
component parts, class letters, class numbers, cutter letters, cutter numbers, etc., then does a
successive series of sorts to put everything in the correct order.
I call the routine with something like:
@sortedcalls = sort sortcall @calls;where @calls is an array containing a list of call numbers
Here's the routine:
sub sortcall { ($ap1, $ap2, $ap3, $ap4, $ap5) = ($a =~ /\s*([a-zA-Z]+)\s*(\d+\.*\d*)\s*\.*([A-Z]+)\s*([0-9]+)\s*(.*)/i); ($bp1, $bp2, $bp3, $bp4, $bp5) = ($b =~ /\s*([a-zA-Z]+)\s*(\d+\.*\d*)\s*\.*([A-Z]+)\s*([0-9]+)\s*(.*)/i); if ($ap1 ne $bp1) # The class letters { return ($ap1 cmp $bp1); } elsif ($ap2 != $bp2) # The classnumbers { return ($ap2 <=> $bp2); } elsif ($ap3 ne $bp3) # The cutter letters { return ($ap3 cmp $bp3); } elsif ($ap4 != $bp4) # The cutter numbers { return ($ap4 <=> $bp4); } elsif ($ap5 ne $bp5) # The leftovers { return ($ap5 cmp $bp5); } else { return 0; } }
Or you can view it as a text file here.
A note regarding the regex: this version assumes a decimal point between the class and cutter numbers, if your call numbers display without a decimal you will probably have to adjust the regex to fit your situation.