web-dev-qa-db-fra.com

Ajouter les suffixes st, nd, rd et th (ordinaux) à un nombre

Je souhaite générer dynamiquement une chaîne de texte basée sur le jour actuel. Ainsi, par exemple, si c'est le jour 1, j'aimerais que mon code génère = "Son <dynamique> 1 * <chaîne dynamique> st </ chaîne dynamique> * </ dynamique>".

Il y a 12 jours au total alors j'ai fait ce qui suit:

  1. J'ai mis en place une boucle for qui parcourt les 12 jours.

  2. Dans mon code HTML, j'ai attribué à mon élément un identifiant unique avec lequel le cibler, voir ci-dessous:

    <h1 id="dynamicTitle" class="CustomFont leftHeading shadow">On The <span></span> <em>of rest of generic text</em></h1>
    
  3. Ensuite, dans ma boucle for, j'ai le code suivant:

    $("#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"
    }
    

METTRE &AGRAVE; JOUR

Ceci est la boucle complète comme demandé:

$(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) {
            }
        }
    }
100
Antonio Vasilev

Les règles sont les suivantes:

  • st est utilisé avec les nombres finissant par 1 (par exemple 1er, prononcé en premier)
  • nd est utilisé avec les nombres finissant par 2 (par exemple 92e, prononcé quatre-vingt-dix secondes)
  • rd est utilisé avec les nombres finissant par 3 (par exemple 33e, prononcé trente-troisième)
  • Par exception aux règles ci-dessus, tous les numéros "adolescents" se terminant par 11, 12 ou 13 utilisent -th (par exemple, 11ème, prononcé onzième, 112ème, Prononcé cent [et] douzième)
  • th est utilisé pour tous les autres nombres (par exemple, 9ème, prononcé neuvième).

Le code JavaScript suivant (réécrit en juin 2014) accomplit ceci:

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

Exemple de sortie pour les nombres compris entre 0 et 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
263
Salman A

De Shopify

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

Approche minimale à une ligne pour les suffixes ordinaux

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

(ceci est pour les entiers positifs, voir ci-dessous pour d'autres variations)

Explication

Commencez avec un tableau avec les suffixes ["st", "nd", "rd"]. Nous voulons mapper des entiers se terminant par 1, 2, 3 (mais ne se terminant pas par 11, 12, 13) aux index 0, 1, 2.

D'autres entiers (y compris ceux se terminant par 11, 12, 13) peuvent être mappés sur autre chose - les index non trouvés dans le tableau auront pour valeur undefined. C'est faux en javascript et avec l'utilisation de logical ou (|| "th"), l'expression retournera "th" pour ces entiers, ce qui est exactement ce que nous voulons.

L'expression ((n + 90) % 100 - 10) % 10 - 1 effectue le mappage. Le décomposer:

  • (n + 90) % 100: Cette expression prend l’entier en entrée - 10 mod 100, mappant 10 à 0, ... 99 à 89, 0 à 90, ..., 9 à 99. Les entiers se terminant par 11, 12, 13 se trouvent maintenant à extrémité inférieure (mappée à 1, 2, 3).
  • - 10: maintenant 10 est mappé à -10, 19 à -1, 99 à 79, 0 à 80, ... 9 à 89. Les entiers se terminant par 11, 12, 13 sont mappés à des entiers négatifs (−9, −8 , -7).
  • % 10: Tous les entiers se terminant par 1, 2 ou 3 sont mappés sur 1, 2, 3. Tous les autres entiers sont mappés sur autre chose (11, 12, 13 sont toujours mappés sur -9, -8, -7).
  • - 1: En soustrayant un, on obtient le mappage final de 1, 2, 3 à 0, 1, 2.

Vérifier que cela fonctionne

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>

Variations

Permettant des nombres entiers négatifs:

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

Dans la syntaxe ES6 Fat Arrow (fonction anonyme):

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

Mettre à jour

Une alternative encore plus courte pour les entiers positifs est l'expression

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

Voir cet article pour une explication.

28
Tomas Langkaas

En scindant le nombre dans un tableau et en inversant le sens, nous pouvons facilement vérifier les 2 derniers chiffres du nombre en utilisant array[0] et array[1]

Si un nombre se trouve dans l'adolescence array[1] = 1, il faut "e".

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

Vous avez seulement 12 jours? Je serais tenté de faire juste un tableau de recherche simple:

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

puis 

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

ou

var i = 8;
var day = i + suffixes[i]; // result: '8th'
7
Jamiec
function getSuffix(n) {return n < 11 || n > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((n - 1) % 10, 3)] : 'th'}
5
Johnny

J'ai écrit cette fonction pour résoudre ce problème:

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

Avec cela, vous pouvez simplement mettre .addSuffix() à n’importe quel nombre et cela donnera ce que vous voulez. Par exemple:

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

Une version alternative de la fonction ordinale pourrait être la suivante:

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

Les variables portent un nom plus explicite, utilisent la convention de casse-chameau et pourraient être plus rapides.

1
Daniel Harvey

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

Voir la version annotée sur https://Gist.github.com/furf/986113#file-annotated-js

Courte, douce et efficace, tout comme les fonctions utilitaires devraient l'être. Fonctionne avec n'importe quel entier/float signé/non signé. (Même si je ne peux pas imaginer le besoin d'ordinaliser des flotteurs)

1
Raine

J'ai écrit cette fonction simple l'autre jour. Bien que, pour une date donnée, vous n'ayez pas besoin des chiffres les plus grands, cela correspond également aux valeurs les plus élevées (1013e, 36021e, etc.

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
Sir Kettle

J'ai écrit cette fonction pour des nombres plus élevés et tous les cas de 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
Amaechi chuks

Voici une autre option.

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'));

Notice the exception for the teens? Teens are so akward!

Edit: Forgot about 11th and 12th

0
Bullyen

Intl.PluralRules, la méthode standard .

Je voudrais juste laisser tomber la méthode canonique ici, car personne ne semble le savoir.

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(100)
        .fill()
        .map((_, index) => index)
        .map(ordinal)
        .join(" ");
console.log(test);

Je le recommande vivement, c'est très facile à lire et à lire. J'espère que ça aide?

  • Il évite l’utilisation d’un nombre entier négatif, c’est-à-dire un nombre inférieur à 1, et renvoie false
  • Il retourne 0 si l'entrée est 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));

SORTIE

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

Je voulais apporter une réponse fonctionnelle à cette question pour compléter la réponse existante:

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)

nous avons créé un tableau des valeurs spéciales. Il est important de se rappeler que les tableaux ont un index de base zéro, de sorte que ordinalSuffix [0] est égal à 'st'. 

Notre fonction numberToOrdinal vérifie si le numéro se termine par un numéro adolescent, auquel cas ajoutez le numéro avec 'th' car tous les nombres ordinaux sont alors 'th'. Dans le cas où le nombre n'est pas un adolescent, nous passons le nombre à addSuffix qui ajoute le nombre à l'ordinal qui est déterminé par si le nombre moins 1 (car nous utilisons un index de base zéro), le mod 10 ayant un reste de 2 ou moins c'est pris dans le tableau, sinon c'est 'th'.

exemple de sortie: 

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
Peter McArthur

Je recommande vivement l'excellente date-fns library. Rapide, modulaire, immuable, fonctionne avec des dates standard.

import * as DateFns from 'date-fns';

const ordinalInt = DateFns.format(someInt, 'do');

Voir docs date-fns: https://date-fns.org/v2.0.0-alpha.9/docs/format

0
Luke Williams

Ancien que j'ai fait pour mes affaires ...

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