2012-09-19 6 views

Respuesta

22
function getOrdinal(n) { 
    var s=["th","st","nd","rd"], 
    v=n%100; 
    return n+(s[(v-20)%10]||s[v]||s[0]); 
} 

, gracias @RobG bits versión modificada

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;  
} 

pruebas

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 
+2

Wow, me tropiezo en Código de golf por error? :) –

+1

También devuelve '1.5th',' udnefinedth', 'NaNth',' trueth' y 'falseth' que pueden ser pintorescos pero parecen menos que útiles. La función probablemente debería probar que la entrada es un número o cadena adecuada (asegurándose de que sea un número entero). Si lo es, devuelve el número más ordinal. De lo contrario, devuelve el valor original. – RobG

+1

Solución agradable y compacta :) – sameera207

2

Puede que le resulte conveniente mono-Patch la función en el prototipo número, por lo que se puede llamar como un método en el número (implementación descaradamente robado de la respuesta de 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]) 
} 

Ejemplo del uso:

var someDay = Math.floor(Math.random() * 31 + 1); 
alert(someDay.toOrdinal()) 

O creáis que es malvado mono de parches; como de costumbre, YMMV.

(a veces llaman a este método particular th, pero que funciona un poco mejor en los idiomas en los que no es necesario el paréntesis de invocación.)

Adición de una explicación de la lógica. Los puntos clave que están en Javascript específica:

  1. El operador % devuelve resultados negativos para un dividendo negativo módulo un divisor positivo (por lo -1 % 5 es -1; muchas otras implementaciones de la devolución operador módulo únicas respuestas entre 0 y n-1, por lo -1 % 5 es 4).
  2. Intentar indexar una matriz por un valor fuera del rango válido de índices (ya sea negativo o pasado el final de la matriz) da como resultado el valor undefined, que es falsey.

La lógica explota estos hechos para devolver el sufijo correcto de una expresión compacta con estas partes.

  1. Intente acceder s[(v-20)%10]. Si v (que es el número de módulo 100 dado) es menor que 20, entonces el índice es negativo y el acceso a la matriz devuelve undefined. De lo contrario, el índice de matriz está entre 0 y 9. Los valores de 0 a 3 devuelven el sufijo correcto correcto ("th", "st", "nd" y "rd"), mientras que cualquier valor mayor que 3 volverá a mostrar undefined.

  2. Si el resultado de 1 es un valor definido, devuélvalo; de lo contrario, intente acceder al s[v]. Si v es en sí mismo 0, 1, 2 o 3, nuevamente obtenemos "th", "st", "nd" o "rd", respectivamente. De lo contrario, obtendremos un valor indefinido y la expresión pasará a la siguiente alternativa.

  3. Si no se define ninguno de los resultados anteriores, devolvemos s[0], que es "th".

El resultado es que todo, desde 4 a 20 - incluyendo 11, 12 y 13 - consigue un "th", mientras que todos los otros números que terminan en 1, 2 ó 3 y obtenga "c", "nd "y" rd ", respectivamente.

+0

Agregar a 'Number.prototype' tiene la ventaja de que solo se debe invocar a valores que en realidad son números. Pero debe probar que el valor es un número entero; de lo contrario, no agregue el ordinal (y devuelva el valor original?). – RobG

+0

Tengo una pregunta rápida por qué 'v-20' y no solo v? – Craicerjack

+0

Copié eso de la respuesta de @ PradeepSanjaya, pero está ahí para lidiar con el hecho de que los números que terminan en 1, 2 y 3 obtienen "st", "nd" y "rd", excepto los números que terminan en 11, 12, y 13, que todos obtienen "th". –

1

La respuesta de Pradeep es genial, pero algo un poco más robusto debería probar el valor y hacer algo sensato si no es un valor adecuado para agregar un ordinal (como simplemente devolver el valor), p.

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 
0
npm install ordinal 

funciona tanto en el navegador y el nodo. A continuación, sólo:

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' 

https://www.npmjs.com/package/ordinal

Cuestiones relacionadas