-
-
Save furf/986113 to your computer and use it in GitHub Desktop.
function( | |
a // number | |
){ | |
return[ | |
"th","st","nd","rd" // array of ordinal suffixes | |
][ | |
(a=~~ // floor the value for usable index (integer) | |
(a<0?-a:a) // absolute value for usable index (positive) | |
%100) // mod 100 to ensure teens edge case is handled every century | |
>10&&a<14 // handle teens edge case where 11-13 return "th" | |
||(a%=10) // mod 10 to check ones column digit | |
>3 // all digits above 3 return "th" | |
?0 // return "th" for above cases | |
:a // return "th", "st", "rd" for others | |
] | |
} |
function b(a){return["th","st","nd","rd"][(a=~~(a<0?-a:a)%100)>10&&a<14||(a%=10)>3?0:a]} |
Copyright (c) 2011 Dave Furfero, http://furf.com | |
Permission is hereby granted, free of charge, to any person obtaining | |
a copy of this software and associated documentation files (the | |
"Software"), to deal in the Software without restriction, including | |
without limitation the rights to use, copy, modify, merge, publish, | |
distribute, sublicense, and/or sell copies of the Software, and to | |
permit persons to whom the Software is furnished to do so, subject to | |
the following conditions: | |
The above copyright notice and this permission notice shall be | |
included in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
{ | |
"name": "ordinal", | |
"description": "Return the ordinal suffix for a number.", | |
"keywords": ["ordinal","number","suffix","string"] | |
} |
thanks! when i originally wrote this snippet, i included the value as well, but the second time i used it, i needed only the returned suffix to place inside a separate span, hidden for accessibility, while visually displaying the inning number (a constraint of the layout). also, a user might want to superscript the suffix. (you can see it in action by inspecting the inning number on the mlb.com homepage scoreboard.) i felt it provided the greater flexibility to exclude it and that it was easy enough to code "n + ordinal(n)" when needed. but for this application, i suppose i have quite a few characters left to make it optional. :)
instead of adding an option, maybe you could also return [num,ord]
? that way it's easy enough to extract what you want.
ordinal(32)[1]
ordinal(32).join('')
Interesting. I would prefer your syntax in the case where the value being passed is not stored.
32+ordinal(32) // looks a little silly
But in other cases, that syntax would be longer. If I were to support the return of the value, the optional concatenation is more terse and provides a more traditional API.
// suffix-only usage
ordinal(n) // current suffix-only
ordinal(n)[1] // return [value, suffix] array
ordinal(n) // optional concatenation
// value-added usage
n+ordinal(n) // current suffix-only
ordinal(n).join('') // return [value, suffix] array
ordinal(n,1) // optional concatenation
PS--I'm really digging the 140bytes project. Lots of good reads. Cheers!
My version.
function(a){return[,"st","nd","rd"][/1?.$/.exec(a)]||"th"}
i like the use of the empty array member. i avoided regexp for performance. http://jsperf.com/ordinals-in-140-bytes (this code actually runs on mlb.com :)) but in the world of code golf you win!
tsaniel's version add's a lot of overhead, buried in the 'regexp black-box'.
If it's code golf we play, then we can't allow ourselves defining a function to get us the decimal exponent:
d = function (i){var l=Math.log; return Math.ceil(l(i)/l(10))}
Here's a version using a map-reduce-like logic
current version here: https://gist.github.com/1308753
// JS converts string-numbers on the fly e.g. "7"&3 >3
// solution with a 'map-reduce' mindset
// similar and more concise solutions could be implemented
// a=(a+'').substr(-2);
ord = function (a){
//summary: cast to string, map (e.g. atomize) and reduce
a=(a+'') //cast to string
.split('') //atomize
.slice(-2) //get the last two elements
.reduce( //reduce arithmetically to a single value
function(a,b){
if(1==a) return 0; //teens case -> return 0 (#el containing 'th')
else return b>3 ? 0 : b; //if b>3 return 0 -> 'th'
}
);
return ['th','st','nd','rd'][a]; //map number to a string
};
another difference between our implementations: mine is the only one to base ordinal suffix on the whole number, not the decimal. since ordinals are natural numbers [0, 1, 2, ...], i felt that the floor of the number was the meaningful part to transform. i could be wrong. i suppose it's a matter of semantics and usage which implementation works best.
so, in seeing these other implementations and thinking it through... in the case of a decimal being passed and the suffix returned being based on a transformation of the passed argument, then jed, your suggestion of returning [n, suffix] would be desirable where n is the floored number. (or n + suffix)
thanks for the posts, guys.
New version with a bitwise trick but only supports non-negative integers:
function(a){return[,'st','nd','rd'][a%100/10^1&&a%10]||'th'}
21th? 22th? 23th?
11st? 12nd? 13rd? Keep trying! :)
i like tsaniels bitwise the best for all practical purposes. non-negative integers are typically all you'll need.
fixd?
function(a){a+="";return(a.charAt(a.length-2)==1)?"th":[,"st","nd","rd"][a.charAt(a.length-1)]||"th"}
Edit:
made it shorter with "%"
function(a){return(a%100>10&&a%100<19)?"th":[,"st","nd","rd"][a%10]||"th"}
Edit:
I just noticed Tsaniel's function... it's shorter than mine, therefore, my function is useless... meh.
@furf: Did you mean you find a bug? But it just works fine with me.
@tsaniel no, he found a bug in my code, I deleted the original post. Your function is perfect.
Oh I see.
Shave another byte off by the way:
function(a){return[,'st','nd','rd'][a/10%10^1&&a%10]||'th'}
great work! just out of curiosity, why no return the ordinalized value instead of just the suffix?