[Python] Convert natural numbers to ordinal numbers

Contents This is a method to convert a natural number of integer type to an ordinal number of string type (0th, 1st, 2nd, 3rd, ..). Here, 0 is also included in the natural number. Each code can be downloaded from the GitHub repository.

Rule Before implementation, first consider the rules by referring to List of notations and readings of English ordinal numbers 1 to 1000.

  1. The ordinal suffix (the string following the number) is basically "th"! (Roughly)
  2. As an exception, if the last digit is 1, it will be "st", if it is 2, it will be "nd", and if it is 3, it will be "rd".
  3. As an exception to the exception rule, if the last two digits are 11, it will be "th" (eleventh).

Solution

Code the above rules in order, and finally refactor (organize the code without changing its behavior).

Package to use:

#Standard library
from collections import defaultdict
Execution environment
OS Windows Subsystem for Linux
Python version 3.8.5

1. Basically "th"

Using the collections package defaultdict [^ 1],

[^ 1]: How to use Python defaultdict

def int2ordinal_1(num):
    ordinal_dict = defaultdict(lambda: "th")
    suffix = ordinal_dict[num]
    return f"{num}{suffix}"

#Indiscriminately"th"return it
print(int2ordinal_1(0))
# -> '0th'
print(int2ordinal_1(1))
# -> '1th':Correspond with rule 2,Correctly 1st'
print(int2ordinal_1(11))
# -> '11th':Correspond with rule 3

2. "st" if the last digit is 1, "nd" if it is 2, "rd" if it is 3.

Update the dictionary.

ordinal_dict.update({1: "st", 2: "nd", 3: "rd"})

Then change it to determine the ordinal number based on the last digit of the input value.

mod = num % 10
suffix = ordinal_dict[mod]

If you add this to the processing inside the function,

def int2ordinal_2(num):
    ordinal_dict = defaultdict(lambda: "th")
    ordinal_dict.update({1: "st", 2: "nd", 3: "rd"})
    mod = num % 10
    suffix = ordinal_dict[mod]
    return f"{num}{suffix}"

print(int2ordinal_2(0))
# -> '0th'
print(int2ordinal_2(1))
# -> '1st'
print(int2ordinal_2(11))
# -> '11st':Correspond with rule 3,Correctly 11th'

3. "th" if the last 2 digits are 11

If you divide by 100 and the remainder is 11, you can return "th", so

if num % 100 == 11:
    suffix = "th"
else:
    suffix = ordinal_dict[mod]

If you add this to the processing inside the function,

def int2ordinal_3(num):
    ordinal_dict = defaultdict(lambda: "th")
    ordinal_dict.update({1: "st", 2: "nd", 3: "rd"})
    mod = num % 10
    if num % 100 == 11:
        suffix = "th"
    else:
        suffix = ordinal_dict[mod]
    return f"{num}{suffix}"

print(int2ordinal_3(0))
# -> '0th'
print(int2ordinal_3(1))
# -> '1st'
print(int2ordinal_3(11))
# -> '11th'

4. Refactoring

It's not a time-consuming process, so it's just a bonus.

num% 100 == 11 is the same as" the remainder when the quotient num // 10 is divided by 10 is 1".

#Change before
mod = num % 10
if num % 100 == 11:
    suffix = "th"
else:
    suffix = ordinal_dict[mod]
#After change
q = num // 10
mod = num % 10
if q % 10 == 1:
    suffix = "th"
else:
    suffix = ordinal_dict[mod]

In addition, the quotient and remainder are calculated at once with the divmod function.

Also, make the if-else statement on one line. This time the effect is weak, but since the number of times to write the algebra suffix is reduced, typographical errors can be reduced.

q, mod = divmod(num, 10)
suffix = "th" if q % 10 == 1 else ordinal_dict[mod]

If you add this to the processing inside the function,

def int2ordinal_4(num):
    ordinal_dict = defaultdict(lambda: "th")
    ordinal_dict.update({1: "st", 2: "nd", 3: "rd"})
    q, mod = divmod(num, 10)
    suffix = "th" if q % 10 == 1 else ordinal_dict[mod]
    return f"{num}{suffix}"

print(int2ordinal_4(0))
# -> '0th'
print(int2ordinal_4(1))
# -> '1st'
print(int2ordinal_4(11))
# -> '11th'

Completed form: a function that returns an ordinal number

It is as follows when the argument type check etc. are added.

ordinal_func.py


def int2ordinal(num):
    """
    Convert a natural number to a ordinal number.

    Args:
        num (int): natural number

    Returns:
        str: ordinal number, like 0th, 1st, 2nd,...

    Notes:
        Zero can be used as @num argument.
    """
    if not isinstance(num, int):
        raise TypeError(
            f"@num must be integer, but {num} was applied.")
    if num < 0:
        raise ValueError(
            f"@num must be over 0, but {num} was applied.")
    ordinal_dict = defaultdict(lambda: "th")
    ordinal_dict.update({1: "st", 2: "nd", 3: "rd"})
    q, mod = divmod(num, 10)
    suffix = "th" if q % 10 == 1 else ordinal_dict[mod]
    return f"{num}{suffix}"

Execution confirmation:

ordinal_func.py


print(int2ordinal(0)) # 0th
print(int2ordinal(1)) # 1st
print(int2ordinal(2)) # 2nd
print(int2ordinal(3)) # 3rd
print(int2ordinal(4)) # 4th
print(int2ordinal(11)) # 11th
print(int2ordinal(21)) # 21st
print(int2ordinal(111)) # 111th
print(int2ordinal(121)) # 121st

Another solution (method without defaultdict)

I will introduce the method without using defaultdict, which was commented by @shiracamus.

def int2ordinal_5(num):
    ordinal_dict = {1: "st", 2: "nd", 3: "rd"}
    q, mod = divmod(num, 10)
    suffix = q % 10 != 1 and ordinal_dict.get(mod) or "th"
    return f"{num}{suffix}"

print(int2ordinal_5(0))
# -> '0th'
print(int2ordinal_5(1))
# -> '1st'
print(int2ordinal_5(11))
# -> '11th'
num q mod q % 10 != 1 ordinal_dict.get(mod) q % 10 != 1 and ordinal_dict.get(mod) suffix
0 0 0 False None False "th"
1 0 1 True "st" "st" "st"
11 1 1 False "st" False "th"

Combining the negative form with ʻand` ...

It's hard to come up with this, but it's convenient to use ʻorfor numeric assignments. For example, you can use it when you want to give an empty list of default arguments for a function. (Note that settingdef func (x = []): x.append (0); return x` etc. in the function argument will cause unexpected behavior![^ 2])

[^ 2]: Note that the default value of the [python] argument is evaluation at definition

def func(values=None):
    values = values or []
    if not isinstance(values, list):
        raise TypeError(f"@values must be a list or None, but {values} was applied.")
    values.append(0)
    return values

If values is None, False, or empty, the empty list[]is assigned. Otherwise, the values argument is used as is.

Afterword

That's how Python can convert natural numbers to ordinal numbers!

Recommended Posts

[Python] Convert natural numbers to ordinal numbers
Convert decimal numbers to n-ary numbers [python]
[python] Convert date to string
Convert numpy int64 to python int
[Python] Convert list to Pandas [Pandas]
Convert Scratch project to Python
[Python] Convert Shift_JIS to UTF-8
Convert python 3.x code to python 2.x
[Python] Convert decimal numbers to binary numbers, octal numbers, and hexadecimal numbers
python, php, ruby How to convert decimal numbers to n-ary numbers
Convert markdown to PDF in Python
Workflow to convert formula (image) to python
Convert list to DataFrame with python
Python> list> Convert double list to single list
Python> tuple> Convert double tuple to single tuple
[Python] Change the alphabet to numbers
[Python] How to get divisors of natural numbers at high speed
[Python] How to convert db file to csv
Convert memo at once with Python 2to3
[Python] How to display random numbers (random module)
[Python] How to convert a 2D list to a 1D list
How to convert Python to an exe file
[Python] Convert csv file delimiters to tab delimiters
Convert psd file to png in Python
Convert Excel data to JSON with python
Convert Hiragana to Romaji with Python (Beta)
Convert from katakana to vowel kana [python]
Convert FX 1-minute data to 5-minute data with Python
python> Convert tuple to list> aList = list (pi_tuple)
Convert Python date types to RFC822 format
Python> Output numbers from 1 to 100, 501 to 600> For csv
Convert HEIC files to PNG files with Python
Convert Chinese numerals to Arabic numerals with Python
Convert from Markdown to HTML in Python
Convert absolute URLs to relative URLs in Python
Sample to convert image to Wavelet with Python
Updated to Python 2.7.9
Convert to HSV
I tried to create a program to convert hexadecimal numbers to decimal numbers with python
"Backport" to python 2
Python code to convert region mesh code to latitude / longitude
Convert FBX files to ASCII <-> BINARY in Python
Python script to convert latitude / longitude to mesh code
[Python] Convert from DICOM to PNG or CSV
Convert svg file to png / ico with Python
Convert Windows epoch values to date with python
How to convert SVG to PDF and PNG [Python]
Convert STL to Voxel mesh using Python VTK
Convert exponential notation float to str in Python
Convert cubic mesh code to WKT in Python
Convert strings to character-by-character list format with python
Convert jupyter notebook .ipynb files to python executable .py files
Python practice Convert the input year to the Japanese calendar
How to convert / restore a string with [] in python
How to convert Python # type for Python super beginners: str
Convert a slice object to a list of index numbers
Python: Natural language processing
Convert 202003 to 2020-03 with pandas
Changes from Python 3.0 to Python 3.5
Convert NumPy array "ndarray" to lilt in Python [tolist ()]
Convert CIDR notation netmask to dotted decimal notation in Python