是否有 JavaScript 代码片段可以取值 1-31 并将其转换为第 1、第 2、第 3 等?
谢谢!
function getOrdinal(n) {
var s=["th","st","nd","rd"],
v=n%100;
return n+(s[(v-20)%10]||s[v]||s[0]);
}
感谢@RobG 位修改版
function getOrdinal(n) {
if((parseFloat(n) == parseInt(n)) && !isNaN(n)){
var s=["th","st","nd","rd"],
v=n%100;
return n+(s[(v-20)%10]||s[v]||s[0]);
}
return n;
}
测试
getOrdinal("test"); // test
getOrdinal(1.5); // 1.5
getOrdinal(1); // 1st
getOrdinal(2); // 2nd
getOrdinal(3); // 3rd
getOrdinal(4); // 4th
getOrdinal(true); // true
getOrdinal(Infinity); // Infinity
getOrdinal(NaN); // NaN
getOrdinal(void 0); // undefined
您可能会发现将函数猴子修补到 Number 原型中很方便,因此您可以将其作为数字上的方法调用(从 Pradeep 的答案中无耻地窃取了实现):
Number.prototype.toOrdinal = function() {
var n = this.valueOf(),
s = [ 'th', 'st', 'nd', 'rd' ],
v = n % 100;
return n + (s[(v-20)%10] || s[v] || s[0])
}
示例使用:
var someDay = Math.floor(Math.random() * 31 + 1);
alert(someDay.toOrdinal())
或者你可能认为猴子补丁是邪恶的;像往常一样,YMMV。
(我有时称这种方法为特殊方法th
,但在不需要括号进行调用的语言中效果更好。)
添加逻辑说明。特定于 Javascript 的关键点:
%
运算符返回负除数模正除数的负结果(所以是-1 % 5
;-1
模运算符的许多其他实现只返回和之间的答案0
,n-1
所以-1 % 5
是4
)。 undefined
值是错误的。逻辑利用这些事实从包含这些部分的紧凑表达式中返回正确的后缀。
尝试访问s[(v-20)%10]
. 如果v
(给定的数以 100 为模)小于 20,则索引为负数并且数组访问返回undefined
. 否则,数组索引在 0 到 9 之间。值 0 到 3 返回正确的关联后缀(“th”、“st”、“nd”和“rd”),而大于 3 的值将再次返回undefined
。
如果 1 的结果是一个定义的值,则返回它;否则,尝试访问s[v]
. 如果v
它本身是 0、1、2 或 3,我们再次分别得到“th”、“st”、“nd”或“rd”。否则,我们会得到一个未定义的值,并且表达式会转到下一个选项。
如果上述结果均未定义,则返回s[0]
,即“th”。
结果是从 4 到 20 的所有数字(包括 11、12 和 13)都得到“th”,而所有其他以 1、2 或 3 结尾的数字都得到“st”、“nd”和“rd”,分别。
Pradeep 的回答很酷,但是如果它不是添加序数的合适值(比如只返回值),那么更强大的东西应该测试该值并做一些明智的事情,例如
var getOrdinal = (function() {
var re = /^\d+$/;
var ordinal = ["th","st","nd","rd"];
return function (value) {
var t;
if (re.test(String(value))) {
t = value % 100;
return t + (ordinal[(t - 20 % 10)] || ordinal[t] || 'th');
}
return value;
}
}());
getOrdinal( void 0 ); // undefined
getOrdinal( ); // undefined
getOrdinal( NaN ); // NaN
getOrdinal( true ); // true
getOrdinal( 1.0 ); // 1st
getOrdinal( '' ); // '' (empty string)
getOrdinal(Infinity); // Infinity
npm install ordinal
适用于浏览器和节点。然后只是:
var ordinal = require('ordinal')
ordinal(1); //=> '1st'
ordinal(2); //=> '2nd'
ordinal(3); //=> '3rd'
ordinal(4); //=> '4th'
ordinal(11); //=> '11th'
ordinal(12); //=> '12th'
ordinal(13); //=> '13th'
ordinal(21); //=> '21st'
ordinal(22); //=> '22nd'
ordinal(23); //=> '23rd'
ordinal(24); //=> '24th'