Добавьте к числу суффикс st, nd, rd и th (порядковый)


150

Я хотел бы динамически генерировать строку текста на основе текущего дня. Так, например, если это день 1, то я бы хотел, чтобы мой код генерировал = "Это <dynamic> 1 * <dynamic string> st </ dynamic string> * </ dynamic>".

Всего 12 дней, поэтому я сделал следующее:

  1. Я установил цикл for, который проходит через 12 дней.

  2. В моем html я дал своему элементу уникальный идентификатор, на который нужно нацелиться, см. Ниже:

    <h1 id="dynamicTitle" class="CustomFont leftHeading shadow">On The <span></span> <em>of rest of generic text</em></h1>
  3. Затем внутри цикла for у меня есть следующий код:

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

ОБНОВИТЬ

Это весь цикл for, как и было запрошено:

$(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
Если ваш исходный код достаточно короткий, не могли бы вы опубликовать полный текст и точно сказать, что не так или что вас смущает?
Рональд Барзелл

Что ваш код делает / не делает в настоящее время? Вы не четко заявили, что происходит не так.
Заостренный

Я предполагаю, что показанный код является содержимым ifблока, который далее содержится в цикле? Показать больше кода ....
MrCode

@MrCode - Да, вы правы. Я обновил пост, чтобы включить весь цикл for. Я надеюсь, что это проясняет!
Антонио Васильев

аккуратно и хорошо работает.
Дэн Джей

Ответы:


346

Эти правила заключаются в следующем:

  • st используется с числами, заканчивающимися на 1 (например, 1st, произносится первым)
  • nd используется с числами, заканчивающимися на 2 (например, 92-й, произносится девяносто второй)
  • rd используется с числами, заканчивающимися на 3 (например, 33-й, произносится как тридцать третий)
  • В качестве исключения из вышеприведенных правил все «подростковые» числа, заканчивающиеся на 11, 12 или 13, используют десятый (например, 11-й, произносится одиннадцатый, 112-й, произносится сто [и] двенадцатый)
  • th используется для всех других чисел (например, 9-й, произносится девятый).

Следующий код JavaScript (переписанный в Jun '14) выполняет это:

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

Пример вывода для чисел от 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
Это хорошо сработало и для моего: dateString = monthNames [newValue.getUTCMonth ()] + "" + numberSuffix (newValue.getUTCDate ()) + "," + newValue.getUTCFullYear ();
Майкл Дж. Калкинс

9
Это не обрабатывает исключения для трех «подростковых» номеров должным образом. Так , например, чисел 111, 112и 113должно привести "111th", "112th"и , "113th"соответственно, не"111st" , "112nd"и "113rd"производится с помощью функции , как в данный момент кодированной.
Мартино

3
Этот ответ, кажется, развился отлично. Спасибо всем участникам.
Лонни Бест

7
Я превратил его в лямбду ES6 без какой-либо реальной причины:n=>n+(n%10==1&&n%100!=11?'st':n%10==2&&n%100!=12?'nd':n%10==3&&n%100!=13?'rd':'th')
Камило Мартин

1
@ Как ни странно, спустя ~ π / 2 года я все еще могу это прочитать.
Камило Мартин

211

От 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
Добавление объяснения может сделать его лучшим ответом!
Пугаж

5
@Pugazh A. найдите s [v% 10], если> = 20 (20-е ... 99-е), B. если не найдено, попробуйте s [v] (0-е. 3-е), C. если все еще не найдено, используйте s [0] (4/19)
Sheepy

4
почему двойной получить в имени функции, хотя?
Гишери

46

Минимальный однострочный подход для порядковых суффиксов

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

(это для натуральных чисел, см. ниже для других вариантов)

объяснение

Начните с массива с суффиксами ["st", "nd", "rd"]. Мы хотим отобразить целые числа, заканчивающиеся на 1, 2, 3 (но не заканчивающиеся на 11, 12, 13), на индексы 0, 1, 2.

Другие целые числа (в том числе заканчивающиеся на 11, 12, 13) могут быть сопоставлены с чем угодно - индексам, не найденным в массиве, будет присвоено значение undefined. Это ложно в javascript и с использованием логического или ( || "th") выражение будет возвращать "th"для этих целых чисел, что именно то, что мы хотим.

Выражение ((n + 90) % 100 - 10) % 10 - 1делает отображение. Разбивая это:

  • (n + 90) % 100: Это выражение принимает входное целое число - 10 mod 100, отображая от 10 до 0, ... от 99 до 89, от 0 до 90, ..., от 9 до 99. Теперь целые числа, заканчивающиеся на 11, 12, 13, находятся ниже конец (сопоставляется с 1, 2, 3).
  • - 10: Теперь 10 отображается в −10, от 19 до -1, от 99 до 79, от 0 до 80, ... от 9 до 89. Целые числа, оканчивающиеся на 11, 12, 13, сопоставляются с отрицательными целыми числами (−9, −8, -7).
  • % 10Теперь все целые числа, оканчивающиеся на 1, 2 или 3, сопоставляются с 1, 2, 3. Все остальные целые числа сопоставляются с чем-то другим (11, 12, 13 по-прежнему сопоставляются с −9, −8, −7).
  • - 1: Вычитание одного дает окончательное отображение от 1, 2, 3 до 0, 1, 2.

Проверка того, что это работает

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>

вариации

Допустимые отрицательные целые числа:

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

В ES6 синтаксис жирной стрелки (анонимная функция):

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

Обновить

Еще более короткой альтернативой для натуральных чисел является выражение

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

Смотрите этот пост для объяснения.

Обновление 2

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

3
элегантный. моя любимая.
парень mograbi


10

Intl.PluralRules, То стандартный метод.

Я просто хотел бы отбросить канонический способ сделать это здесь, поскольку никто, кажется, не знает этого.

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
Это единственное хорошее общее решение, так как здесь единственный ответ, который обрабатывает отрицательные числа.
RobG

7

У тебя есть только 12 дней? Я бы соблазнился сделать это просто простым поисковым массивом:

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

затем

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

или

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

Спасибо, это решило мою проблему. Я не смог получить суффикс, совпадающий с днем, поэтому я просто заполнил массив цифрами и суффиксом, который работает отлично. Я тогда просто назвал это как$("#dynamicTitle span").html(suffix[i-1]);
Антонио Васильев

7

Разбивая число на массив и обращая его, мы можем легко проверить последние 2 цифры числа, используя array[0]и array[1].

Если число в подростковом возрасте, array[1] = 1это требует "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";
}

Это потрясающе. Спасибо!
Джейсон

Вы должны исключить 11, 12, 13
PSS

2
@psx Вот для чего условие в строке 5.
Ник

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

Хороший маленький вкладчик, просто немного трудно понять
Bryc

Сбой, где n == 0 из-за n - 1части (возвращает неопределенное). Также не работает для чисел больше 110, например, getSuffix(111)возвращает "st". Это решает проблему ОП, где числа от 1 до 12, но не является общим решением. :-(
RobG

2

Я написал эту функцию, чтобы решить эту проблему:

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

При этом вы можете просто поставить .addSuffix()на любое число, и это приведет к тому, что вы хотите. Например:

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

Я думаю, что numberв этой строке var lastDigits=n.substring(number.length-2);следует изменить наthis
Слава Абакумов

это должно быть nвместо this, но спасибо за указание на эту ошибку! :)
Джиммери

2

Альтернативная версия порядковой функции может быть следующей:

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

Переменные названы более явно, использует соглашение о верблюдах и может быть быстрее.


Однако это не будет работать для локализованных баз кода.
Даниэль Харви

1

Я написал эту простую функцию на днях. Хотя для даты вам не нужны большие числа, это будет учитывать и более высокие значения (1013, 36021 и т. Д.)

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

См аннотированную версию на https://gist.github.com/furf/986113#file-annotated-js

Короткий, приятный и эффективный, как и должны быть полезны функции. Работает с любым знаковым / без знака целым числом / с плавающей точкой. (Даже если я не могу представить необходимость ординализации поплавков)


0

Вот еще один вариант.

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

Обратите внимание на исключение для подростков? Подростки такие неловкие!

Изменить: забыл про 11 и 12


0

Я хотел дать функциональный ответ на этот вопрос, чтобы дополнить существующий ответ:

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)

мы создали массив специальных значений, важно помнить, что массивы имеют нулевой индекс, поэтому ordinalSuffix [0] равен 'st'.

Наша функция numberToOrdinal проверяет, заканчивается ли число на младший номер, и в этом случае добавляется число с «th», так как все порядковые номера чисел «th». В случае, если число не является подростком, мы передаем число в addSuffix, который добавляет число к порядковому номеру, определяемому, если у числа минус 1 (потому что мы используем индекс на основе нуля) мод 10 имеет остаток 2 или меньше он берется из массива, в противном случае это 'th'.

образец вывода:

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

Старый я сделал для своих вещей ...

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

Настоятельно рекомендуем отличную библиотеку date-fns . Быстрый, модульный, неизменный, работает со стандартными датами.

import * as DateFns from 'date-fns';

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

Смотрите документы date-fns: https://date-fns.org/v2.0.0-alpha.9/docs/format.


0

Я написал эту функцию для больших чисел и всех тестовых случаев

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

Вот немного другой подход (я не думаю, что другие ответы делают это). Я не уверен, люблю ли я это или ненавижу это, но это работает!

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

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

0

Это для одних лайнеров и любителей эс6

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

Другой вариант для + be number будет:

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

Также, чтобы избавиться от порядкового префикса, просто используйте эти:

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

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

не стесняйтесь изменять в соответствии с вашими потребностями


0

Вы также можете использовать scales::ordinal()функцию. Это быстро и просто в использовании.

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

-1

Я настоятельно рекомендую это, это очень легко и просто читать. Надеюсь, это поможет?

  • Это позволяет избежать использования отрицательного целого числа, т. Е. Числа меньше 1, и возвращает false
  • Возвращает 0, если вход 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));

ВЫВОД

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

-7

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

Ты можешь использовать

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

для позиционирования суффикса


4
Это не то, о чем просил ОП
TetraDev
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.