Dodaj sufiks st, nd, rd i th (porządkowy) do liczby

150

Chciałbym dynamicznie generować ciąg tekstowy na podstawie bieżącego dnia. Na przykład, jeśli jest dzień 1, chciałbym, aby mój kod wygenerował = "To <dynamic> 1 * <ciąg dynamiczny> st </ ciąg dynamiczny> * </dynamic>".

Łącznie jest 12 dni, więc wykonałem następujące czynności:

  1. Skonfigurowałem pętlę for, która zapętla się przez 12 dni.

  2. W moim html dałem swojemu elementowi unikalny identyfikator, za pomocą którego mam go kierować, patrz poniżej:

    <h1 id="dynamicTitle" class="CustomFont leftHeading shadow">On The <span></span> <em>of rest of generic text</em></h1>
  3. Następnie w mojej pętli for mam następujący kod:

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

AKTUALIZACJA

To jest cała pętla for zgodnie z żądaniem:

$(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) {
            }
        }
    }
Antonio Vasilev
źródło
1
Jeśli Twój kod źródłowy jest wystarczająco krótki, czy mógłbyś zamieścić całą treść, a także powiedzieć dokładnie, co jest nie tak lub co Cię dezorientuje?
RonaldBarzell
Co obecnie robi / nie robi Twój kod? Nie określiłeś jasno, co się dzieje.
Pointy
Zgaduję, że pokazany kod jest zawartością ifbloku, który jest dalej zawarty w pętli? Pokaż więcej kodu ....
MrCode
@MrCode - Tak, masz rację. Zaktualizowałem post, aby zawierał całą pętlę for. Mam nadzieję, że to wyjaśnia wszystko!
Antonio Vasilev
schludny i działa dobrze.
Dan Jay,

Odpowiedzi:

345

Te zasady są następujące:

  • st jest używany z liczbami kończącymi się na 1 (np. 1., wymawiane jako pierwsze)
  • nd jest używane z liczbami kończącymi się na 2 (np. 92. wymawiane jako dziewięćdziesiąt sekund)
  • rd jest używany z liczbami kończącymi się na 3 (np. 33., wymawiane jako trzydzieste trzecie)
  • Jako wyjątek od powyższych zasad, wszystkie „nastoletnie” liczby kończące się na 11, 12 lub 13 używają -ty (np. 11, wymawiane jako jedenaste, 112, wymawiane sto [i] dwunaste)
  • th jest używany dla wszystkich innych liczb (np. 9, wymawiane jako dziewiąte).

Następujący kod JavaScript (przepisany w czerwcu 2014) umożliwia to:

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

Przykładowe dane wyjściowe dla liczb od 0 do 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
Salman A
źródło
1
U mnie też zadziałało bardzo dobrze: dateString = monthNames [newValue.getUTCMonth ()] + "" + numberSuffix (newValue.getUTCDate ()) + "," + newValue.getUTCFullYear ();
Michael J. Calkins,
9
Nie obsługuje to poprawnie wyjątków dla trzech „nastolatków”. Na przykład liczby 111, 112i 113powinno spowodować "111th", "112th"i "113th"odpowiednio nie"111st" , "112nd"oraz "113rd"wytwarzane przez funkcję jak obecnie kodowanej.
martineau
3
Wydaje się, że ta odpowiedź ewoluowała doskonale. Dziękuję wszystkim współpracownikom.
Lonnie Best,
7
Sprawdziłem to jako lambdę ES6 bez żadnego powodu: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, co zabawne, po ~ π / 2 latach nadal mogę to przeczytać.
Camilo Martin,
210

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

Fizer Khan
źródło
22
Dodanie wyjaśnienia może sprawić, że będzie to lepsza odpowiedź!
Pugazh
5
@Pugazh A. find s [v% 10] if> = 20 (20 ... 99th), B. jeśli nie znaleziono, spróbuj s [v] (0th..3rd), C. jeśli nadal nie znaleziono, użyj s [0] (4–19)
Sheepy
4
dlaczego jednak podwójne get w nazwie funkcji?
Gisheri
46

Minimalne jednowierszowe podejście do przyrostków porządkowych

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

(dotyczy dodatnich liczb całkowitych, zobacz poniżej inne odmiany)

Wyjaśnienie

Zacznij od tablicy z przyrostkami ["st", "nd", "rd"]. Chcemy zmapować liczby całkowite kończące się na 1, 2, 3 (ale nie kończące się na 11, 12, 13) na indeksy 0, 1, 2.

Inne liczby całkowite (w tym kończące się na 11, 12, 13) można odwzorować na cokolwiek innego - indeksy nie znalezione w tablicy będą obliczane do undefined. To jest fałszywe w javascript i przy użyciu logiki lub ( || "th") wyrażenie zwróci"th" dla tych liczb całkowitych, co jest dokładnie tym, czego chcemy.

Wyrażenie ((n + 90) % 100 - 10) % 10 - 1wykonuje mapowanie. Rozbijając to:

  • (n + 90) % 100: To wyrażenie przyjmuje wejściową liczbę całkowitą - 10 mod 100, odwzorowując 10 na 0, ... 99 do 89, 0 do 90, ..., 9 do 99. Teraz liczby całkowite kończące się na 11, 12, 13 znajdują się na niższym koniec (mapowany na 1, 2, 3).
  • - 10: Teraz 10 jest mapowane na −10, 19 na −1, 99 do 79, 0 do 80, ... 9 do 89. Liczby całkowite kończące się na 11, 12, 13 są odwzorowywane na ujemne liczby całkowite (−9, −8, −7).
  • % 10: Teraz wszystkie liczby całkowite kończące się na 1, 2 lub 3 są mapowane na 1, 2, 3. Wszystkie inne liczby całkowite są mapowane na coś innego (11, 12, 13 są nadal mapowane na -9, -8, -7).
  • - 1: Odejmowanie jednego daje końcowe mapowanie 1, 2, 3 na 0, 1, 2.

Sprawdzam, czy to działa

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>

Wariacje

Zezwalanie na ujemne liczby całkowite:

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

W składni grubej strzałki ES6 (funkcja anonimowa):

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

Aktualizacja

Jeszcze krótszą alternatywą dla dodatnich liczb całkowitych jest wyrażenie

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

Zobacz ten post aby uzyskać wyjaśnienie.

Zaktualizuj 2

[,'st','nd','rd'][n/10%10^1&&n%10]||'th'
Tomas Langkaas
źródło
3
elegancki. mój ulubiony.
guy mograbi
10

Intl.PluralRules, metoda standardowa .

Chciałbym po prostu zrezygnować z kanonicznego sposobu robienia tego tutaj, ponieważ nikt o tym nie wie.

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

Константин Ван
źródło
1
To jedyne dobre rozwiązanie ogólne, ponieważ jest to jedyna odpowiedź, która obsługuje liczby ujemne.
RobG
7

Masz tylko 12 dni? Kusiłbym, aby uczynić to zwykłą tablicą wyszukiwania:

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

następnie

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

lub

var i = 8;
var day = i + suffixes[i]; // result: '8th'
Jamiec
źródło
Dzięki, to rozwiązało mój problem. Nie mogłem dopasować sufiksu do dnia, więc po prostu zapełniłem tablicę zarówno liczbami, jak i sufiksem, który działa idealnie. Wtedy po prostu nazwałem to tak$("#dynamicTitle span").html(suffix[i-1]);
Antonio Vasilev
7

Dzieląc liczbę na tablicę i odwracając, możemy łatwo sprawdzić ostatnie 2 cyfry numeru za pomocą array[0]i array[1].

Jeśli liczba jest nastolatką array[1] = 1, wymaga „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";
}
nacięcie
źródło
To jest doskonałe. Dzięki!
Jason
Musisz wykluczyć 11, 12, 13
psx
2
@psx Do tego służy warunek w linii 5.
nick
4
function getSuffix(n) {return n < 11 || n > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((n - 1) % 10, 3)] : 'th'}
Jasio
źródło
Ładny, mały oneliner, tylko trochę trudny do zrozumienia
bryc
Niepowodzenie, gdzie n == 0 z powodu n - 1części (zwraca wartość niezdefiniowaną). Błąd również dla liczb większych niż 110, np. getSuffix(111)Zwraca „st”. Rozwiązuje problem PO, w którym liczby wynoszą od 1 do 12, ale nie jest rozwiązaniem ogólnym. :-(
RobG
2

Napisałem tę funkcję, aby rozwiązać ten problem:

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

Dzięki temu możesz po prostu wpisać .addSuffix()dowolną liczbę, a otrzymasz to, co chcesz. Na przykład:

var number=1234;
console.log(number.addSuffix());
// console will show: 1234th
Jimmery
źródło
Myślę, że numberw tym ciągu var lastDigits=n.substring(number.length-2);należy zmienić nathis
Slava Abakumov
powinno być nzamiast this, ale dziękuję za wskazanie tego błędu! :)
Jimmery
2

Alternatywna wersja funkcji porządkowej mogłaby wyglądać następująco:

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

Zmienne są nazywane bardziej jawnie, używają konwencji wielbłądziej wielkości i mogą być szybsze.

Daniel Harvey
źródło
Nie zadziała to jednak w przypadku zlokalizowanych baz kodu.
Daniel Harvey,
1

Napisałem tę prostą funkcję pewnego dnia. Chociaż na randkę nie potrzebujesz większych liczb, będzie to również uwzględniać wyższe wartości (1013, 36021 itd.)

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;
};
Sir Kettle
źródło
1

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

Zobacz wersję z adnotacjami na https://gist.github.com/furf/986113#file-annotated-js

Krótkie, słodkie i wydajne, tak jak powinny być funkcje użytkowe. Działa z każdą liczbą całkowitą / zmiennoprzecinkową ze znakiem / bez znaku. (Nawet jeśli nie wyobrażam sobie potrzeby uporządkowania pływaków)

hndcrftd
źródło
0

Oto inna opcja.

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

Zwróć uwagę na wyjątek dla nastolatków? Nastolatki są takie dziwne!

Edycja: zapomniałem o jedenastym i dwunastym

Bullyen
źródło
0

Chciałem udzielić funkcjonalnej odpowiedzi na to pytanie, aby uzupełnić istniejącą odpowiedź:

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)

stworzyliśmy tablicę wartości specjalnych, ważną rzeczą do zapamiętania jest to, że tablice mają indeks zaczynający się od zera, więc ordinalSuffix [0] jest równe „st”.

Nasza funkcja numberToOrdinal sprawdza, czy liczba kończy się liczbą nastolatków, w którym to przypadku należy dodać do liczby „th”, ponieważ wszystkie liczby porządkowe to „th”. W przypadku, gdy liczba nie jest nastolatką, przekazujemy liczbę do addSuffix, która dodaje liczbę do liczby porządkowej, która jest określana przez to, czy liczba minus 1 (ponieważ używamy indeksu od zera) mod 10 ma resztę 2 lub mniej jest pobierany z tablicy, w przeciwnym razie jest to „th”.

przykładowe wyjście:

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
Peter McArthur
źródło
0

Stary, który zrobiłem dla moich rzeczy ...

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;
     }
}
user10304
źródło
Dodaj opis powyższego kodu. Pomogłoby to znacznie więcej niż kawałek kodu.
Mathews Sunny
0

Zdecydowanie polecam doskonałą bibliotekę date-fns . Szybki, modułowy, niezmienny, działa ze standardowymi datami.

import * as DateFns from 'date-fns';

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

Zobacz dokumentację date-fns: https://date-fns.org/v2.0.0-alpha.9/docs/format

Freewalker
źródło
0

Napisałem tę funkcję dla wyższych liczb i wszystkich przypadków testowych

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')
    }
}
Amaechi chuks
źródło
0

Oto nieco inne podejście (nie sądzę, aby inne odpowiedzi to robiły). Nie jestem pewien, czy to kocham, czy nienawidzę, ale działa!

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

    return `${day}${suffixes.substring(startIndex, startIndex + 2)}`;
  }
Dave Cooper
źródło
0

To jest dla jednego liniowca i miłośników 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

Inną opcją dla + be number byłoby:

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

Aby pozbyć się przedrostka porządkowego, po prostu użyj tych:

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

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

możesz dowolnie modyfikować w zależności od potrzeb

Pedro JR
źródło
0

Możesz także użyć scales::ordinal()funkcji. Jest szybki i prosty w użyciu.

scales::ordinal(1:12)
## [1] "1st"  "2nd"  "3rd"  "4th"  "5th"  "6th"  "7th"  "8th"  "9th"  "10th" "11th" "12th"
phargart
źródło
-1

Zdecydowanie polecam, jest to bardzo łatwe i proste do odczytania. Mam nadzieję, że to pomoże?

  • Pozwala uniknąć użycia ujemnej liczby całkowitej, tj. Liczby mniejszej niż 1 i zwraca fałsz
  • Zwraca 0, jeśli wejście wynosi 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));

WYNIK

false
0
11th
15th
21st
32nd
43rd
70th
111th
300th
101st
an-apluss
źródło
-7

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

Możesz użyć

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

do umieszczania przyrostka

Vishnu Vikraman
źródło
4
Nie o to prosił PO
TetraDev