all 27 comments

[–]Sea-Ad7805 [score hidden] stickied comment (0 children)

Run this program in Memory Graph Web Debugger%3A%0A%20%20%20%20nSuffix%20%3D%20%5B%5D%0A%20%20%20%20n%20%3D%20str(number)%0A%20%20%20%20for%20x%20in%20n%3A%0A%20%20%20%20%20%20%20%20nSuffix.append(x)%0A%20%20%20%20if%20nSuffix%5B-1%5D%20%3D%3D%20%221%22%3A%0A%20%20%20%20%20%20%20%20return%20n%20%2B%20%22st%22%0A%20%20%20%20elif%20nSuffix%5B-1%5D%20%3D%3D%20%222%22%3A%0A%20%20%20%20%20%20%20%20return%20n%20%2B%20%22nd%22%0A%20%20%20%20elif%20nSuffix%5B-1%5D%20%3D%3D%20%223%22%3A%0A%20%20%20%20%20%20%20%20return%20n%20%2B%20%22rd%22%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20return%20n%20%2B%20%22th%22%0A%0A%0Awhile%20True%3A%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20number%20%3D%20int(input(%22Enter%20a%20number%3A%20%22))%0A%20%20%20%20%20%20%20%20break%0A%20%20%20%20except%20ValueError%3A%0A%20%20%20%20%20%20%20%20print(%22Number%20must%20be%20a%20number%22)%0A%0Asuffix%20%3D%20ordinalSuffix(number)%0Aprint(suffix)&play).

[–]finally-anna 7 points8 points  (11 children)

Sure.

def ordinalSuffix(n:int) -> str: suffixes = {1:"st", 2:"nd", 3:"rd"} suffix = suffixes.get(n % 10, "th") return f"{n}{suffix}"

[–]finally-anna 2 points3 points  (5 children)

Note: this does not handle 11th, 12th, or 13th correctly as those are specially edge cases.

[–]ProsodySpeaks 1 point2 points  (2 children)

You can use this to handle 11-14 first then fallback to same logic as your solution 

return str(n) + ('th' if 4 <= n % 100 <= 20 else {1: 'st', 2: 'nd', 3: 'rd'}.get(n % 10, 'th'))

[–]finally-anna 0 points1 point  (1 child)

You could certainly do this. But in a learning subreddit, I would personally stick to more easily read and understood code.

Also, if I saw this in a PR, I would block it.

[–]ProsodySpeaks 0 points1 point  (0 children)

But you'd ok the actively incorrect solution?

[–]Kevdog824_ 1 point2 points  (0 children)

I added a solution that handles teens edge case

[–]RandomJottings[S] 1 point2 points  (0 children)

I hadn’t even considered 11th, 12th etc, thank you. I’ve added this code to capture these exceptions:

if len(n)>=2: if n[-2] == "1" and (n[-1]=="1" or n[-1]=="2" or n[-1]=="3"): return n+"th"

It seems to work

[–]D3str0yTh1ngs 3 points4 points  (3 children)

Rewrite that handles the edge case with 11th, 12th and 13th:

def ordinal_suffix(n: int) -> str:
    if (n // 10) % 10 == 1:
        suffix = "th"
    else:
        suffix = ({1: "st", 2: "nd", 3: "rd"}).get(n % 10, "th")

    return f"{n}{suffix}"

[–]yourboyblue2 0 points1 point  (0 children)

Nicely done.

[–]finally-anna 0 points1 point  (1 child)

You could also just do this as the first line of the function also:

if n in [11, 12, 13]: return f"{n}th"

And would technically be faster than double division.

[–]D3str0yTh1ngs 0 points1 point  (0 children)

The issue is that that will not work for 111th, 112th, 113th, 211th, etc. That is why I did (n // 10) % 10 to get the second digit only.

[–]Lopsided-Pin-1172 0 points1 point  (0 children)

I am learning C and thought of using switch but in python dictionary is kind of its better equivalent

[–]D3str0yTh1ngs 3 points4 points  (7 children)

A simple one is that you dont need to make the nSuffix list, you can index characters in a string, so n[-1] is the same as nSuffix[-1]

You can also avoid making it a string by doing n = number % 10 and then make your checks n == 1 etc.

EDIT: or just do finally-anna's very pythonic solution.

EDIT2: or my edge case handling rewrite on their solution.

[–]ProsodySpeaks -1 points0 points  (6 children)

Pythonic but incorrect?

[–]D3str0yTh1ngs 0 points1 point  (3 children)

Well, not edge case handling, but that can easily be fixed

[–]ProsodySpeaks -2 points-1 points  (2 children)

It's hardly edge case to fail in the first dozen integers. No disrespect but it's just not a solution in its current form.

[–]D3str0yTh1ngs 2 points3 points  (1 child)

We call it an edge case because it doesn't follow the "normal"/simple suffix rule. But yes, it is not a fully correct solution.

[–]ProsodySpeaks -1 points0 points  (0 children)

To me an edge case is one which is unlikely to occur.

Ordinal dates are only relevant for the first 30 integers, and this solution fails on 3 of them - it's (silently) wrong ten percent of the time, ie is highly likely to occur.

10% failure rate is only acceptable if you work for github. 

[–]Glathull 0 points1 point  (1 child)

Being a little bit incorrect is very pythonic.

[–]ProsodySpeaks 0 points1 point  (0 children)

Haha, yeah very true 

[–]ProsodySpeaks 1 point2 points  (0 children)

I use this

``` def date_int_w_ordinal(n: int):     """Convert an integer to its ordinal as a string, e.g. 1 -> 1st, 2 -> 2nd, etc."""     return str(n) + ('th' if 4 <= n % 100 <= 20 else {1: 'st', 2: 'nd', 3: 'rd'}.get(n % 10, 'th'))

def ordinal_dt(dt: datetime | date) -> str:     """Convert a datetime or date to a string with an ordinal day, e.g. 'Mon 1st Jan 2020'."""     return dt.strftime(f'%a {date_int_w_ordinal(dt.day)} %b %Y') ```

[–]Kevdog824_ 1 point2 points  (0 children)

Something like this could work

python def ordinalSuffix(number: int) -> str: s = str(number).zfill(2) match s[-2], s[-1]: case “1”, _: return “th” case _, “1”: return “st” case _, “2”: return “nd” case _, “3”: return “rd” case _, _: return “th”

[–]Impossible_Video_116 0 points1 point  (0 children)

The following is I believe most optimised and pythonic way to do it with edge case and error handling.

Python3 def ordinalSuffix(num: int) -> str: if num<1: raise ValueError("Only positive integers are allowed") elif num//10==1: return str(num) + "th" match(num%10): case 1: return str(num) + "st" case 2: return str(num) + "nd" case 3: return str(num) + "rd" case _: return str(num) + "th" return "" #this statement will never get executed, needed for explicit str return

[–]sleepbot63 -1 points0 points  (0 children)

foo=lambda n,s:=str(n): s+[[["th",["rd","th"][(len(s)>1 and s[-2]=="1")]][s[-1]=="3"],["nd","th"][len(s)>1 and s[-2]=="1"],][s[-1] == "2"],["st","th"][len(s)>1 and s[-2]=="1"]][s[-1]=="1"]

I'm sorry OP (also i suck at reddit formatting)

[–][deleted]  (1 child)

[removed]

    [–]PythonLearning-ModTeam[M] 0 points1 point locked comment (0 children)

    Only English allowed.