Aggiungi il suffisso st, nd, rd e th (ordinale) a un numero


150

Vorrei generare dinamicamente una stringa di testo basata su un giorno corrente. Quindi, per esempio, se è il primo giorno, vorrei che il mio codice generasse = "È il <dinamico> 1 * <stringa dinamica> st </ stringa dinamica> * </dinamica>".

Ci sono 12 giorni in totale, quindi ho fatto quanto segue:

  1. Ho creato un ciclo for che scorre attraverso i 12 giorni.

  2. Nel mio HTML ho dato al mio elemento un ID univoco con cui indirizzarlo, vedi sotto:

    <h1 id="dynamicTitle" class="CustomFont leftHeading shadow">On The <span></span> <em>of rest of generic text</em></h1>
  3. Quindi, all'interno del mio ciclo for ho il seguente codice:

    $("#dynamicTitle span").html(i);
    var day = i;
    if (day == 1) {
        day = i + "st";
    } else if (day == 2) {
        day = i + "nd"
    } else if (day == 3) {
        day = i + "rd"
    }

AGGIORNARE

Questo è l'intero ciclo for come richiesto:

$(document).ready(function () {
    for (i = 1; i <= 12; i++) {
        var classy = "";
        if (daysTilDate(i + 19) > 0) {
            classy = "future";
            $("#Day" + i).addClass(classy);
            $("#mainHeading").html("");
            $("#title").html("");
            $("#description").html("");
        } else if (daysTilDate(i + 19) < 0) {
            classy = "past";
            $("#Day" + i).addClass(classy);
            $("#title").html("");
            $("#description").html("");
            $("#mainHeading").html("");
            $(".cta").css('display', 'none');
            $("#Day" + i + " .prizeLink").attr("href", "" + i + ".html");
        } else {
            classy = "current";
            $("#Day" + i).addClass(classy);
            $("#title").html(headings[i - 1]);
            $("#description").html(descriptions[i - 1]);
            $(".cta").css('display', 'block');
            $("#dynamicImage").attr("src", ".." + i + ".jpg");
            $("#mainHeading").html("");
            $(".claimPrize").attr("href", "" + i + ".html");
            $("#dynamicTitle span").html(i);
            var day = i;
            if (day == 1) {
                day = i + "st";
            } else if (day == 2) {
                day = i + "nd"
            } else if (day == 3) {
                day = i + "rd"
            } else if (day) {
            }
        }
    }

1
Se il tuo codice sorgente è abbastanza breve, ti dispiacerebbe pubblicare tutto e dire esattamente cosa è sbagliato o cosa ti confonde?
RonaldBarzell,

Cos'è che il tuo codice fa / non fa attualmente? Non hai dichiarato chiaramente cosa non va.
Punta il

Immagino che il codice mostrato sia il contenuto di un ifblocco che è ulteriormente contenuto dal loop? Mostra altro codice ....
MrCode

@MrCode - Sì, hai ragione. Ho aggiornato il post per includere l'intero ciclo for. Spero che questo chiarisca!
Antonio Vasilev,

pulito e funziona bene.
Dan Jay

Risposte:


345

Le regole sono le seguenti:

  • la m viene usata con i numeri che terminano con 1 (es. 1 °, pronunciato per primo)
  • nd viene utilizzato con numeri che terminano con 2 (ad es. 92 °, pronunciato novanta secondi)
  • rd viene utilizzato con numeri che terminano con 3 (ad es. 33 °, pronunciato trentatreesimo)
  • In deroga alle regole di cui sopra, tutti i numeri "adolescenti" che terminano con 11, 12 o 13 usano -th (es. Undicesimo, pronunciato undicesimo, 112 °, pronunciato cento [e] dodicesimo)
  • viene usato per tutti gli altri numeri (es. 9 °, pronunciato nono).

Il seguente codice JavaScript (riscritto nel giugno '14) compie questo:

function ordinal_suffix_of(i) {
    var j = i % 10,
        k = i % 100;
    if (j == 1 && k != 11) {
        return i + "st";
    }
    if (j == 2 && k != 12) {
        return i + "nd";
    }
    if (j == 3 && k != 13) {
        return i + "rd";
    }
    return i + "th";
}

Esempio di output per numeri tra 0-115:

  0  0th
  1  1st
  2  2nd
  3  3rd
  4  4th
  5  5th
  6  6th
  7  7th
  8  8th
  9  9th
 10  10th
 11  11th
 12  12th
 13  13th
 14  14th
 15  15th
 16  16th
 17  17th
 18  18th
 19  19th
 20  20th
 21  21st
 22  22nd
 23  23rd
 24  24th
 25  25th
 26  26th
 27  27th
 28  28th
 29  29th
 30  30th
 31  31st
 32  32nd
 33  33rd
 34  34th
 35  35th
 36  36th
 37  37th
 38  38th
 39  39th
 40  40th
 41  41st
 42  42nd
 43  43rd
 44  44th
 45  45th
 46  46th
 47  47th
 48  48th
 49  49th
 50  50th
 51  51st
 52  52nd
 53  53rd
 54  54th
 55  55th
 56  56th
 57  57th
 58  58th
 59  59th
 60  60th
 61  61st
 62  62nd
 63  63rd
 64  64th
 65  65th
 66  66th
 67  67th
 68  68th
 69  69th
 70  70th
 71  71st
 72  72nd
 73  73rd
 74  74th
 75  75th
 76  76th
 77  77th
 78  78th
 79  79th
 80  80th
 81  81st
 82  82nd
 83  83rd
 84  84th
 85  85th
 86  86th
 87  87th
 88  88th
 89  89th
 90  90th
 91  91st
 92  92nd
 93  93rd
 94  94th
 95  95th
 96  96th
 97  97th
 98  98th
 99  99th
100  100th
101  101st
102  102nd
103  103rd
104  104th
105  105th
106  106th
107  107th
108  108th
109  109th
110  110th
111  111th
112  112th
113  113th
114  114th
115  115th

1
Ha funzionato davvero bene anche per il mio: dateString = monthNames [newValue.getUTCMonth ()] + "" + numberSuffix (newValue.getUTCDate ()) + "," + newValue.getUTCFullYear ();
Michael J. Calkins,

9
Questo non gestisce correttamente le eccezioni per i tre numeri "adolescenti". Ad esempio i numeri 111, 112e 113dovrebbe comportare "111th", "112th"e "113th"rispettivamente, non il "111st", "112nd"e "113rd"prodotto dalla funzione attualmente codificato.
martineau,

3
Questa risposta sembra essersi evoluta perfettamente. Grazie a tutti i collaboratori.
Lonnie Best

7
L'ho compresso come un lambda ES6 senza una vera ragione:n=>n+(n%10==1&&n%100!=11?'st':n%10==2&&n%100!=12?'nd':n%10==3&&n%100!=13?'rd':'th')
Camilo Martin

1
@Anomaly abbastanza stranamente, dopo ~ π / 2 anni dopo riesco ancora a leggerlo.
Camilo Martin

211

Da Shopify

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

[-4,-1,0,1,2,3,4,10,11,12,13,14,20,21,22,100,101,111].forEach(
  n => console.log(n + ' -> ' + getNumberWithOrdinal(n))
);


22
L'aggiunta di spiegazioni può renderlo una risposta migliore!
Pugazh,

5
@Pugazh A. find s [v% 10] if> = 20 (20th ... 99th), B. se non trovato, prova s ​​[v] (0th..3rd), C. se non ancora trovato, usa s [0] (4th..19th)
Sheepy

4
perché il doppio ottiene il nome della funzione però?
Gisheri,

46

Approccio minimo a una riga per i suffissi ordinali

function nth(n){return["st","nd","rd"][((n+90)%100-10)%10-1]||"th"}

(questo è per numeri interi positivi, vedi sotto per altre variazioni)

Spiegazione

Inizia con un array con i suffissi ["st", "nd", "rd"]. Vogliamo mappare numeri interi che terminano con 1, 2, 3 (ma non terminano con 11, 12, 13) agli indici 0, 1, 2.

Altri numeri interi (compresi quelli che terminano con 11, 12, 13) possono essere associati a qualsiasi altra cosa - verranno valutati gli indici non trovati nell'array undefined. Questo è errato in JavaScript e con l'uso di logico o ( || "th") l'espressione tornerà"th" per questi numeri interi, che è esattamente ciò che vogliamo.

L'espressione ((n + 90) % 100 - 10) % 10 - 1esegue il mapping. Abbattendo:

  • (n + 90) % 100: Questa espressione accetta l'input intero - 10 mod 100, mappando da 10 a 0, ... da 99 a 89, da 0 a 90, ..., da 9 a 99. Ora i numeri interi che terminano con 11, 12, 13 sono in basso end (mappato a 1, 2, 3).
  • - 10: Ora 10 è mappato a −10, 19 a −1, 99 a 79, 0 a 80, ... 9 a 89. Gli interi che terminano in 11, 12, 13 sono mappati su numeri interi negativi (−9, −8, -7).
  • % 10: Ora tutti gli interi che terminano con 1, 2 o 3 sono mappati su 1, 2, 3. Tutti gli altri numeri interi sono mappati su qualcos'altro (11, 12, 13 sono ancora mappati su −9, −8, −7).
  • - 1: Sottraendo uno si ottiene la mappatura finale di 1, 2, da 3 a 0, 1, 2.

Verifica che funzioni

function nth(n){return["st","nd","rd"][((n+90)%100-10)%10-1]||"th"}

//test integers from 1 to 124
for(var r = [], i = 1; i < 125; i++) r.push(i + nth(i));

//output result
document.getElementById('result').innerHTML = r.join('<br>');
<div id="result"></div>

variazioni

Consentire numeri interi negativi:

function nth(n){return["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"}

Nella sintassi della freccia grassa ES6 (funzione anonima):

n=>["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"

Aggiornare

Un'alternativa ancora più breve per numeri interi positivi è l'espressione

[,'st','nd','rd'][n%100>>3^1&&n%10]||'th'

Vedi questo post per una spiegazione.

Aggiornamento 2

[,'st','nd','rd'][n/10%10^1&&n%10]||'th'

3
elegante. il mio preferito.
guy mograbi,


10

Intl.PluralRules, il metodo standard .

Vorrei solo abbandonare il modo canonico di farlo qui, poiché nessuno sembra saperlo.

const english_ordinal_rules = new Intl.PluralRules("en", {type: "ordinal"});
const suffixes = {
	one: "st",
	two: "nd",
	few: "rd",
	other: "th"
};
function ordinal(number) {
	const suffix = suffixes[english_ordinal_rules.select(number)];
	return (number + suffix);
}

const test = Array(201)
	.fill()
	.map((_, index) => index - 100)
	.map(ordinal)
	.join(" ");
console.log(test);


1
Questa è l'unica buona soluzione generale in quanto è l'unica risposta qui che gestisce i numeri negativi.
RobG

7

Hai solo 12 giorni? Sarei tentato di renderlo solo un semplice array di ricerca:

var suffixes = ['','st','nd','rd','th','th','th','th','th','th','th','th','th'];

poi

var i = 2;
var day = i + suffixes[i]; // result: '2nd'

o

var i = 8;
var day = i + suffixes[i]; // result: '8th'

Grazie, questo ha risolto il mio problema. Non sono riuscito a ottenere il suffisso per abbinare il giorno, quindi ho appena popolato l'array con entrambi i numeri e il suffisso che funziona perfettamente. L'ho semplicemente chiamato così$("#dynamicTitle span").html(suffix[i-1]);
Antonio Vasilev,

7

Dividendo il numero in un array e invertendo possiamo facilmente controllare le ultime 2 cifre del numero usando array[0]earray[1] .

Se un numero è negli adolescenti array[1] = 1, richiede "th".

function getDaySuffix(num)
{
    var array = ("" + num).split("").reverse(); // E.g. 123 = array("3","2","1")

    if (array[1] != "1") { // Number is in the teens
        switch (array[0]) {
            case "1": return "st";
            case "2": return "nd";
            case "3": return "rd";
        }
    }

    return "th";
}

Questo è perfetto. Grazie!
Jason,

Devi escludere l'11, 12, 13
psx il

2
@psx Ecco a cosa serve la condizione sulla linea 5.
nick

4
function getSuffix(n) {return n < 11 || n > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((n - 1) % 10, 3)] : 'th'}

Simpatico piccolo interlocutore, un po 'difficile da capire
bryc

Non riesce dove n == 0 a causa della n - 1parte (restituisce undefined). Inoltre non riesce per numeri superiori a 110, ad es. getSuffix(111)Restituisce "st". Risolve il problema del PO in cui i numeri sono compresi tra 1 e 12, ma non è una soluzione generale. :-(
RobG

2

Ho scritto questa funzione per risolvere questo problema:

// this is for adding the ordinal suffix, turning 1, 2 and 3 into 1st, 2nd and 3rd
Number.prototype.addSuffix=function(){
    var n=this.toString().split('.')[0];
    var lastDigits=n.substring(n.length-2);
    //add exception just for 11, 12 and 13
    if(lastDigits==='11' || lastDigits==='12' || lastDigits==='13'){
        return this+'th';
    }
    switch(n.substring(n.length-1)){
        case '1': return this+'st';
        case '2': return this+'nd';
        case '3': return this+'rd';
        default : return this+'th';
    }
};

Con questo puoi semplicemente mettere .addSuffix()qualsiasi numero e si tradurrà in quello che vuoi. Per esempio:

var number=1234;
console.log(number.addSuffix());
// console will show: 1234th

Penso che numberin questa stringa var lastDigits=n.substring(number.length-2);dovrebbe essere cambiato inthis
Slava Abakumov,

dovrebbe essere ninvece di this, ma grazie per aver segnalato quel bug! :)
Jimmery,

2

Una versione alternativa della funzione ordinale potrebbe essere la seguente:

function toCardinal(num) {
    var ones = num % 10;
    var tens = num % 100;

    if (tens < 11 || tens > 13) {
        switch (ones) {
            case 1:
                return num + "st";
            case 2:
                return num + "nd";
            case 3:
                return num + "rd";
        }
    }

    return num + "th";
}

Le variabili sono denominate in modo più esplicito, usano la convenzione del caso del cammello e potrebbero essere più veloci.


Tuttavia, ciò non funzionerà con basi di codice localizzate.
Daniel Harvey,

1

Ho scritto questa semplice funzione l'altro giorno. Anche se per una data non hai bisogno di numeri più grandi, questo soddisferà anche valori più alti (1013 °, 36021 ° ecc ...)

var fGetSuffix = function(nPos){

    var sSuffix = "";

    switch (nPos % 10){
        case 1:
            sSuffix = (nPos % 100 === 11) ? "th" : "st";
            break;
        case 2:
            sSuffix = (nPos % 100 === 12) ? "th" : "nd";
            break;
        case 3:
            sSuffix = (nPos % 100 === 13) ? "th" : "rd";
            break;
        default:
            sSuffix = "th";
            break;
    }

    return sSuffix;
};

1

function ordsfx(a){return["th","st","nd","rd"][(a=~~(a<0?-a:a)%100)>10&&a<14||(a%=10)>3?0:a]}

Vedi la versione annotata su https://gist.github.com/furf/986113#file-annotated-js

Breve, dolce ed efficiente, proprio come dovrebbero essere le funzioni di utilità. Funziona con qualsiasi numero intero / float con o senza segno. (Anche se non riesco a immaginare la necessità di ordinare i galleggianti)


0

Ecco un'altra opzione.

function getOrdinalSuffix(day) {
        
   	if(/^[2-3]?1$/.test(day)){
   		return 'st';
   	} else if(/^[2-3]?2$/.test(day)){
   		return 'nd';
   	} else if(/^[2-3]?3$/.test(day)){
   		return 'rd';
   	} else {
   		return 'th';
   	}
        
}
    
console.log(getOrdinalSuffix('1'));
console.log(getOrdinalSuffix('13'));
console.log(getOrdinalSuffix('22'));
console.log(getOrdinalSuffix('33'));

Notare l'eccezione per gli adolescenti? Gli adolescenti sono così premurosi!

Modifica: dimenticato l'11 e il 12


0

Volevo fornire una risposta funzionale a questa domanda per integrare la risposta esistente:

const ordinalSuffix = ['st', 'nd', 'rd']
const addSuffix = n => n + (ordinalSuffix[(n - 1) % 10] || 'th')
const numberToOrdinal = n => `${n}`.match(/1\d$/) ? n + 'th' : addSuffix(n)

abbiamo creato una matrice di valori speciali, la cosa importante da ricordare è che le matrici hanno un indice in base zero quindi ordinalSuffix [0] è uguale a "st".

Il nostro numero di funzione ToOrdinal verifica se il numero termina con un numero di teenager, nel qual caso aggiungi il numero con 'th' poiché tutti gli ordinali di numeri sono 'th'. Nel caso in cui il numero non sia un adolescente, passiamo il numero ad addSuffix che aggiunge il numero all'ordinale, che è determinato se il numero meno 1 (perché stiamo usando un indice in base zero) mod 10 ha un resto di 2 o meno è preso dall'array, altrimenti è 'th'.

uscita campione:

numberToOrdinal(1) // 1st
numberToOrdinal(2) // 2nd
numberToOrdinal(3) // 3rd
numberToOrdinal(4) // 4th
numberToOrdinal(5) // 5th
numberToOrdinal(6) // 6th
numberToOrdinal(7) // 7th
numberToOrdinal(8) // 8th
numberToOrdinal(9) // 9th
numberToOrdinal(10) // 10th
numberToOrdinal(11) // 11th
numberToOrdinal(12) // 12th
numberToOrdinal(13) // 13th
numberToOrdinal(14) // 14th
numberToOrdinal(101) // 101st

0

Quello vecchio che ho fatto per le mie cose ...

function convertToOrdinal(number){
    if (number !=1){
        var numberastext = number.ToString();
        var endchar = numberastext.Substring(numberastext.Length - 1);
        if (number>9){
            var secondfromendchar = numberastext.Substring(numberastext.Length - 1);
            secondfromendchar = numberastext.Remove(numberastext.Length - 1);
        }
        var suffix = "th";
        var digit = int.Parse(endchar);
        switch (digit){
            case 3:
                if(secondfromendchar != "1"){
                    suffix = "rd";
                    break;
                }
            case 2:
                if(secondfromendchar != "1"){
                    suffix = "nd";
                    break;
                }
            case 1:
                if(secondfromendchar != "1"){
                    suffix = "st";
                    break;
                }
            default:
                suffix = "th";
                break;
         }
            return number+suffix+" ";
     } else {
            return;
     }
}

Aggiungi una descrizione del codice sopra. Aiuterebbe molto più di un pezzo di codice.
Mathews Sunny,


0

Ho scritto questa funzione per numeri più alti e tutti i casi di test

function numberToOrdinal(num) {
    if (num === 0) {
        return '0'
    };
    let i = num.toString(), j = i.slice(i.length - 2), k = i.slice(i.length - 1);
    if (j >= 10 && j <= 20) {
        return (i + 'th')
    } else if (j > 20 && j < 100) {
        if (k == 1) {
            return (i + 'st')
        } else if (k == 2) {
            return (i + 'nd')
        } else if (k == 3) {
            return (i + 'rd')
        } else {
            return (i + 'th')
        }
    } else if (j == 1) {
        return (i + 'st')
    } else if (j == 2) {
        return (i + 'nd')
    } else if (j == 3) {
        return (i + 'rd')
    } else {
        return (i + 'th')
    }
}

0

Ecco un approccio leggermente diverso (non credo che le altre risposte lo facciano). Non sono sicuro se lo adoro o lo odio, ma funziona!

export function addDaySuffix(day: number) { 
  const suffixes =
      '  stndrdthththththththththththththththththstndrdthththththththst';
    const startIndex = day * 2;

    return `${day}${suffixes.substring(startIndex, startIndex + 2)}`;
  }

0

Questo è per una fodera e per gli amanti di es6

let i= new Date().getDate 

// I can be any number, for future sake we'll use 9

const j = I % 10;
const k = I % 100;

i = `${i}${j === 1 &&  k !== 11 ? 'st' : j === 2 && k !== 12 ? 'nd' : j === 3 && k !== 13 ? 'rd' : 'th'}`}

console.log(i) //9th

Un'altra opzione per + essere numero sarebbe:

console.log(["st","nd","rd"][((i+90)%100-10)%10-1]||"th"]

Anche per sbarazzarsi del prefisso ordinale basta usare questi:

console.log(i.parseInt("8th"))

console.log(i.parseFloat("8th"))

sentiti libero di modificare secondo le tue necessità


0

Puoi anche usare la scales::ordinal()funzione. È veloce e semplice da usare.

scales::ordinal(1:12)
## [1] "1st"  "2nd"  "3rd"  "4th"  "5th"  "6th"  "7th"  "8th"  "9th"  "10th" "11th" "12th"

-1

Consiglio vivamente questo, è super facile e semplice da leggere. Spero che ti aiuti

  • Evita l'uso di numeri interi negativi, cioè numero inferiore a 1 e restituisce false
  • Restituisce 0 se l'ingresso è 0
function numberToOrdinal(n) {

  let result;

  if(n < 0){
    return false;
  }else if(n === 0){
    result = "0";
  }else if(n > 0){

    let nToString = n.toString();
    let lastStringIndex = nToString.length-1;
    let lastStringElement = nToString[lastStringIndex];

    if( lastStringElement == "1" && n % 100 !== 11 ){
      result = nToString + "st";
    }else if( lastStringElement == "2" && n % 100 !== 12 ){
      result = nToString + "nd";
    }else if( lastStringElement == "3" && n % 100 !== 13 ){
      result = nToString + "rd";
    }else{
      result = nToString + "th";
    }

  }

  return result;
}

console.log(numberToOrdinal(-111));
console.log(numberToOrdinal(0));
console.log(numberToOrdinal(11));
console.log(numberToOrdinal(15));
console.log(numberToOrdinal(21));
console.log(numberToOrdinal(32));
console.log(numberToOrdinal(43));
console.log(numberToOrdinal(70));
console.log(numberToOrdinal(111));
console.log(numberToOrdinal(300));
console.log(numberToOrdinal(101));

PRODUZIONE

false
0
11th
15th
21st
32nd
43rd
70th
111th
300th
101st

-7

<p>31<sup>st</sup> March 2015</p>

Puoi usare

1<sup>st</sup> 2<sup>nd</sup> 3<sup>rd</sup> 4<sup>th</sup>

per posizionare il suffisso


4
Questo non è ciò che l'OP stava chiedendo
TetraDev
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.