Welcome, guest | Sign In | My Account | Store | Cart

This function converts 0 and positive integers (or their string representations) to their ordinal values. For example, it would convert 0 to "0th", 1 to "1st", 2 to "2nd", 3 to "3rd" and so on.

Python, 54 lines
 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54``` ```#!/usr/bin/env python def ordinal(value): """ Converts zero or a *postive* integer (or their string representations) to an ordinal value. >>> for i in range(1,13): ... ordinal(i) ... u'1st' u'2nd' u'3rd' u'4th' u'5th' u'6th' u'7th' u'8th' u'9th' u'10th' u'11th' u'12th' >>> for i in (100, '111', '112',1011): ... ordinal(i) ... u'100th' u'111th' u'112th' u'1011th' """ try: value = int(value) except ValueError: return value if value % 100//10 != 1: if value % 10 == 1: ordval = u"%d%s" % (value, "st") elif value % 10 == 2: ordval = u"%d%s" % (value, "nd") elif value % 10 == 3: ordval = u"%d%s" % (value, "rd") else: ordval = u"%d%s" % (value, "th") else: ordval = u"%d%s" % (value, "th") return ordval if __name__ == '__main__': import doctest doctest.testmod() ```

This is a quick way to get a more reader-friendly ordinal value for zero and positive integers (including their string representations). The recipe was inspired by the similarly named "ordinal" template tag from Django's humanize module.

grist 14 years, 4 months ago

Code doesn't quite work properly... '11' becomes '11st' '12' becomes '12nd'

grist 14 years, 4 months ago

Not sure about Python, but in perl I did this...

sub ordinal { my \$rawvalue = int(shift); # keep the original so we can return it later my \$value = \$rawvalue % 100; #only need the last 2 digits for what we're doing my \$suffix; if (\$value == 11 || \$value == 12 || \$value == 13) { \$suffix = 'th'; } elsif (\$value % 10 == 1) { \$suffix = 'st'; } elsif (\$value % 10 == 2) { \$suffix = 'nd'; } elsif (\$value % 10 == 3) { \$suffix = 'rd'; } else { \$suffix = 'th'; } return "\$rawvalue\$suffix"; }

Which deals correctly with 11,12 etc and also deals with numbers of any length.

grist 14 years, 4 months ago

Bah, formatting fail.

``````sub ordinal {
my \$rawvalue = int(shift);
my \$value = \$rawvalue % 100;
my \$suffix;
if (\$value == 11 || \$value == 12 || \$value == 13) {
\$suffix = 'th';
} elsif (\$value % 10 == 1) {
\$suffix = 'st';
} elsif (\$value % 10 == 2) {
\$suffix = 'nd';
} elsif (\$value % 10 == 3) {
\$suffix = 'rd';
} else {
\$suffix = 'th';
}
return "\$rawvalue\$suffix";
}
``````

Hi gist, I don't seem to be getting the same errors as you. The function seems to work fine.

``````>>> ordinal(111)
u'111th'
>>> ordinal('111')
u'111th'
>>> ordinal(112)
u'112th'
>>> ordinal(11)
u'11th'
>>> ordinal('111')
u'111th'
>>> ordinal(12)
u'12th'
>>> ordinal('112')
u'112th'
>>> for x in (1,2,3,'4',11,19,101):
...     ordinal(x)
...
u'1st'
u'2nd'
u'3rd'
u'4th'
u'11th'
u'19th'
u'101st'
>>>
``````

Can you provide any more specifics that might help debug? If it helps, I'm using the function with Python 2.6.2 on Ubuntu 9.04. Regards, Serdar

Grist, There was indeed a mistake in the original code: I accidentally dropped the outer "else" clause when pasting it over to ActiveState (though my local code was correct, which is why the function was working for me). I've updated the recipe and it should work now. I've also noted more emphatically that this only works for positive integers or their string representations.

Apologies to folks who this might have confused/frustrated.

Cheers!

 Created by Serdar Tumgoren on Wed, 19 Aug 2009 (MIT)