2012-09-19 3 views

risposta

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

Grazie @RobG bit versione modificata

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

Test

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, ho inciampare in codice Golf per errore? :) –

+1

Restituisce anche '1.5th',' udnefinedth', 'NaNth',' trueth' e 'falseth' che potrebbero essere caratteristici ma che sembrano meno utili. La funzione dovrebbe probabilmente verificare che l'input sia un numero o una stringa appropriata (assicurandosi che sia un numero intero potrebbe essere sufficiente). Se lo è, restituire il numero più ordinale. Altrimenti, restituire il valore originale. – RobG

+1

Soluzione semplice e compatta :) – sameera207

2

Si potrebbe trovare conveniente scimmia-patch la funzione nel prototipo numero, così si può chiamare come metodo sul numero (implementazione svergognata dalla risposta di 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]) 
} 

Esempio utilizzo:

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

Oppure si può credere che Scimmia Patching Is Evil; come al solito, YMMV.

(a volte mi chiamano questo particolare metodo di th, ma che funziona un po 'meglio in lingue in cui non ti servono le parentesi per invocazione.)

Aggiunta di una spiegazione della logica. Punti chiave che sono Javascript-specifica:

  1. L'operatore % restituisce risultati negativi per un dividendo negativo Modulo un divisore positivo (così -1 % 5 è -1; molte altre implementazioni del modulo di ritorno operatore solo risposte tra 0 e n-1, così -1 % 5 è 4).
  2. Il tentativo di indicizzare una matrice per un valore esterno all'intervallo valido di indici (negativo o passato alla fine della matrice) ha come risultato il valore undefined, che è falso.

La logica sfrutta questi fatti per restituire il suffisso corretto da un'espressione compatta con queste parti.

  1. Prova ad accedere a s[(v-20)%10]. Se v (che è il numero dato modulo 100) è inferiore a 20, l'indice è negativo e l'accesso all'array restituisce undefined. In caso contrario, l'indice dell'array è compreso tra 0 e 9. I valori da 0 a 3 restituiscono il suffisso associato corretto ("th", "st", "nd" e "rd"), mentre qualsiasi valore maggiore di 3 restituirà nuovamente undefined.

  2. Se il risultato di 1 è un valore definito, restituirlo; in caso contrario, provare ad accedere a s[v]. Se v è esso stesso 0, 1, 2 o 3, otteniamo nuovamente "th", "st", "nd" o "rd" rispettivamente. Altrimenti, otteniamo un valore non definito e l'espressione passa alla successiva alternativa.

  3. Se nessuno dei risultati sopra indicati è definito, restituiamo s[0], che è "th".

Il risultato è che tutto, da 4 a 20 - di cui 11, 12, e 13 - ottiene un "th", mentre tutti gli altri numeri che terminano con 1, 2 o 3 ottenere "st", "nd ", e" rd ", rispettivamente.

+0

L'aggiunta a 'Number.prototype' ha il vantaggio di dover essere richiamata solo su valori che sono in realtà numeri. Ma dovrebbe verificare che il valore sia un numero intero, altrimenti non aggiungere l'ordinale (e restituire il valore originale?). – RobG

+0

Ho una rapida domanda sul perché 'v-20' e non solo v? – Craicerjack

+0

ho copiato che da @ risposta di PradeepSanjaya, ma è lì a che fare con il fatto che i numeri che terminano in 1, 2, e 3 ricevi "st", "nd", e "rd" - fatta eccezione per i numeri che terminano con 11, 12, e 13, che ottengono tutti "th". –

1

La risposta di Pradeep è interessante, ma qualcosa di un po 'più robusto dovrebbe testare il valore e fare qualcosa di sensato se non è un valore adatto per aggiungere un ordinale (ad esempio, basta restituire il valore), ad es.

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 

funziona sia il browser e il nodo. Poi basta:

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

Problemi correlati