I’m wondering if there is a quick and easy way to output ordinals given a number in python.
For example, given the number 1, I’d like to output "1st", the number 2, "2nd", et cetera, et cetera.
This is for working with dates in a breadcrumb trail
Home > Venues > Bar Academy > 2009 > April > 01
is what is currently shown
I’d like to have something along the lines of
Home > Venues > Bar Academy > 2009 > April > 1st
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Or shorten David’s answer with:
if 4 <= day <= 20 or 24 <= day <= 30:
suffix = "th"
else:
suffix = ["st", "nd", "rd"][day % 10 - 1]
Method 2
Here’s a more general solution:
def ordinal(n):
if 10 <= n % 100 < 20:
return str(n) + 'th'
else:
return str(n) + {1 : 'st', 2 : 'nd', 3 : 'rd'}.get(n % 10, "th")
Method 3
Not sure if it existed 5 years ago when you asked this question, but the inflect package has a function to do what you’re looking for:
>>> import inflect >>> p = inflect.engine() >>> for i in range(1,32): ... print p.ordinal(i) ... 1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th 16th 17th 18th 19th 20th 21st 22nd 23rd 24th 25th 26th 27th 28th 29th 30th 31st
Method 4
These days I’d use Arrow http://arrow.readthedocs.io/en/latest/ (which definately wasn’t around in ’09)
>>> import arrow
>>> from datetime import datetime
>>> arrow.get(datetime.utcnow()).format('Do')
'27th'
Method 5
Here it is using dictionaries as either a function or as a lambda…
If you look at the dictionaries backwards you can read it as…
Everything ends in ‘th’
…unless it ends in 1, 2, or 3 then it ends in ‘st’, ‘nd’, or ‘rd’
…unless it ends in 11, 12, or 13 then it ends in ‘th, ‘th’, or ‘th’
# as a function
def ordinal(num):
return '%d%s' % (num, { 11: 'th', 12: 'th', 13: 'th' }.get(num % 100, { 1: 'st',2: 'nd',3: 'rd',}.get(num % 10, 'th')))
# as a lambda
ordinal = lambda num : '%d%s' % (num, { 11: 'th', 12: 'th', 13: 'th' }.get(num % 100, { 1: 'st',2: 'nd',3: 'rd',}.get(num % 10, 'th')))
Method 6
A more general and shorter solution (as a function):
def get_ordinal(num)
ldig = num % 10
l2dig = (num // 10) % 10
if (l2dig == 1) or (ldig > 3):
return '%d%s' % (num, 'th')
else:
return '%d%s' % (num, {1: 'st', 2: 'nd', 3: 'rd'}.get(ldig))
I just combined David’s solutions and libraries (as deegeedubs did). You can even replace the variables (ldig, l2dig) for the real math (since l2dig is used only once), then you get four lines of code.
Method 7
I made a function that seems to work in this case. Just pass in a date object, and it will use the day to figure out the suffix. Hope it helps
from datetime import date
def get_day_ordinal(d):
sDay = '%dth'
if d.day <= 10 or d.day >= 21:
sDay = '%dst' if d.day % 10 == 1 else sDay
sDay = '%dnd' if d.day % 10 == 2 else sDay
sDay = '%drd' if d.day % 10 == 3 else sDay
return sDay % d.day
d = date.today()
print get_day_ordinal(d)
Method 8
Except for 1st, 2nd, and 3rd, I think they all just add th… 4th, 5th, 6th, 11th, 21st … oh, oops 😉
I think this might work:
def ordinal(num):
ldig = num % 10
l2dig = (num // 10) % 10
if l2dig == 1:
suffix = 'th'
elif ldig == 1:
suffix = 'st'
elif ldig == 2:
suffix = 'nd'
elif ldig == 3:
suffix = 'rd'
else:
suffix = 'th'
return '%d%s' % (num, suffix)
Method 9
def ordinal(n):
return ["th", "st", "nd", "rd"][n%10 if n%10<4 and not (10<n%100<14) else 0]
Method 10
Here is an even shorter general solution:
def foo(n):
return str(n) + {1: 'st', 2: 'nd', 3: 'rd'}.get(4 if 10 <= n % 100 < 20 else n % 10, "th")
Although the other solutions above are probably easier to understand at first glance, this works just as well while using a bit less code.
Method 11
Fixed for negative-inputs, based on eric.frederich’s nice sol’n (just added abs when using %):
def ordinal(num):
return '%d%s' % (num, { 11: 'th', 12: 'th', 13: 'th'}.get(abs(num) % 100, { 1: 'st',2: 'nd',3: 'rd',}.get(abs(num) % 10, 'th')))
Method 12
I wanted to use ordinals for a project of mine and after a few prototypes I think this method although not small will work for any positive integer, yes any integer.
It works by determiniting if the number is above or below 20, if the number is below 20 it will turn the int 1 into the string 1st , 2 , 2nd; 3, 3rd; and the rest will have “st” added to it.
For numbers over 20 it will take the last and second to last digits, which I have called the tens and unit respectively and test them to see what to add to the number.
This is in python by the way, so I’m not sure if other languages will be able to find the last or second to last digit on a string if they do it should translate pretty easily.
def o(numb):
if numb < 20: #determining suffix for < 20
if numb == 1:
suffix = 'st'
elif numb == 2:
suffix = 'nd'
elif numb == 3:
suffix = 'rd'
else:
suffix = 'th'
else: #determining suffix for > 20
tens = str(numb)
tens = tens[-2]
unit = str(numb)
unit = unit[-1]
if tens == "1":
suffix = "th"
else:
if unit == "1":
suffix = 'st'
elif unit == "2":
suffix = 'nd'
elif unit == "3":
suffix = 'rd'
else:
suffix = 'th'
return str(numb)+ suffix
I called the function “o” for ease of use and can be called by importing the file name which I called “ordinal” by import ordinal then ordinal.o(number).
Let me know what you think 😀
P.S. I’ve posted this answer on another ordinals question but realised this one is more applicable considering it’s python.
Method 13
I had to convert a script over from javascript where I had a useful fn that replicated phps date obj. Very similar
def ord(n):
return str(n)+("th" if 4<=n%100<=20 else {1:"st",2:"nd",3:"rd"}.get(n%10, "th"))
this tied in with my date styler:
def dtStylish(dt,f):
return dt.strftime(f).replace("{th}", ord(dt.day))
ps -I got here from another thread which was reported as a duplicate but it wasn’t entirely since that thread also addressed the date issue
Method 14
Here’s a function I wrote as part of a calendar type of program I wrote (I’m not including the whole program). It adds on the correct ordinal for any number greater than 0. I included a loop to demo the output.
def ordinals(num):
# st, nums ending in '1' except '11'
if num[-1] == '1' and num[-2:] != '11':
return num + 'st'
# nd, nums ending in '2' except '12'
elif num[-1] == '2' and num[-2:] != '12':
return num + 'nd'
# rd, nums ending in '3' except '13'
elif num[-1] == '3' and num[-2:] != '13':
return num + 'rd'
# th, all other nums
else:
return num + 'th'
data = ''
# print the first 366 ordinals (for leap year)
for i in range(1, 367):
data += ordinals(str(i)) + 'n'
# print results to file
with open('ordinals.txt', 'w') as wf:
wf.write(data)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0