【问题标题】:Add st, nd, rd and th (ordinal) suffix to a number给数字添加 st、nd、rd 和 th(序数)后缀
【发布时间】:2012-11-17 14:47:59
【问题描述】:

我想根据当前日期动态生成一串文本。因此,例如,如果是第 1 天,那么我希望我的代码生成 = "Its the 1*ststring>*" .

总共有 12 天,所以我做了以下事情:

  1. 我已经设置了一个循环 12 天的 for 循环。

  2. 在我的 html 中,我给了我的元素一个唯一的 id 来定位它,见下文:

    <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) {
            }
        }
    }

【问题讨论】:

  • 如果您的源代码足够短,您是否介意发布完整的内容,并准确说明哪里出了问题或让您感到困惑?
  • 您的代码当前执行/不执行的操作是什么?您没有明确说明出了什么问题。
  • 我猜显示的代码是循环进一步包含的if 块的内容?显示更多代码....
  • @MrCode - 是的,你是对的。我已经更新了帖子以包含整个 for 循环。我希望这能解决问题!
  • 整洁,效果很好。

标签: javascript jquery numbers


【解决方案1】:

rules如下:

  • st 用于以 1 结尾的数字(例如 1st,首先发音)
  • nd 用于以 2 结尾的数字(例如 92nd,发音为 90 秒)
  • rd 用于以 3 结尾的数字(例如 33rd,发音为 33)
  • 作为上述规则的一个例外,所有以 11、12 或 13 结尾的“青少年”数字都使用 -th(例如 11th,发音为 11th,112th, 发音为一百 [和] 十二)
  • th 用于所有其他数字(例如 9th,发音为 9th)。

以下 JavaScript 代码(在 2014 年 6 月重写)实现了这一点:

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

【讨论】:

  • 它对我也很有效: dateString = monthNames[newValue.getUTCMonth()] + " " + numberSuffix(newValue.getUTCDate()) + ", " + newValue.getUTCFullYear();
  • 这不能正确处理三个“青少年”数字的异常。例如,数字 111112113 应分别导致 "111th""112th""113th"不是 "111st""112nd",和"113rd" 由当前编码的函数产生。
  • 这个答案似乎已经完美进化。感谢所有贡献者。
  • 我无缘无故地将它作为 ES6 lambda 压缩:n=&gt;n+(n%10==1&amp;&amp;n%100!=11?'st':n%10==2&amp;&amp;n%100!=12?'nd':n%10==3&amp;&amp;n%100!=13?'rd':'th')
  • @Anomaly 有趣的是,在 ~π/2 年后我仍然可以阅读它。
【解决方案2】:

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

【讨论】:

  • 添加解释可以更好的回答!
  • @Pugazh A. 如果 >= 20 (20th...99th) 则找到 s[v%10],如果未找到则 B. , 尝试 s[v] (0th..3rd), C. 如果仍然没有找到,使用 s[0] (4th..19th)
  • 为什么要在函数名中出现双重输入?
【解决方案3】:

序数后缀的最小单行方法

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>');
&lt;div id="result"&gt;&lt;/div&gt;

变化

允许负整数:

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

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

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

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

在 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'

请参阅this post 了解说明。

更新 2

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

【讨论】:

  • 优雅。我的最爱。
【解决方案4】:

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

【讨论】:

  • @RobG Thomas Langkaas 的回答,他说的例子允许负数,不允许负数?
  • @RobG 我还是最喜欢这个,部分原因是你可以本地化它。
  • @RobG,@BobRhodes,你尝试过负数的变体function nth(n){return["st","nd","rd"][(((n&lt;0?-n:n)+90)%100-10)%10-1]||"th"}吗?它对我来说很好,我现在也添加了代码来演示。
  • 感谢分享这个解决方案!喜欢我可以利用预先存在的功能。
【解决方案5】:

您可以使用moment libraries local data functions

代码:

moment.localeData().ordinal(1)
//1st

【讨论】:

    【解决方案6】:

    通过将数字拆分为数组并反转,我们可以使用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
    • @psx 这就是第 5 行的条件。
    • “数字在十几岁”应该是“数字不在十几岁”。 :-)
    【解决方案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]);
    • 由于从第 4 个索引开始的所有内容都相同,您可以使用 suffixes = ['th','st','nd','rd']; d = i + (suffixes[i] || suffixes[0]);。 :-)
    【解决方案8】:
    function getSuffix(n) {return n < 11 || n > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((n - 1) % 10, 3)] : 'th'}
    

    【讨论】:

    • 不错的小oneliner,只是有点难以理解
    • 由于n - 1 部分导致 n == 0 失败(返回未定义)。对于大于 110 的数字也会失败,例如getSuffix(111) 返回“st”。它确实解决了数字为 1 到 12 的 OP 问题,但不是通用解决方案。 :-(
    【解决方案9】:

    我写了这个函数来解决这个问题:

    // 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,但感谢您指出该错误! :)
    【解决方案10】:

    序数函数的替代版本如下:

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

    变量命名更明确,使用驼峰式约定,可能更快。

    【讨论】:

    • 这不适用于本地化代码库。
    【解决方案11】:

    前几天我写了这个简单的函数。虽然对于某个日期您不需要更大的数字,但这也可以满足更高的值(1013th、36021st 等...)

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

    【讨论】:

      【解决方案12】:

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

      https://gist.github.com/furf/986113#file-annotated-js查看注释版本

      短小精悍且高效,正如实用函数应有的那样。适用于任何有符号/无符号整数/浮点数。 (尽管我无法想象需要对浮点数进行排序)

      【讨论】:

        【解决方案13】:

        强烈推荐优秀的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

        【讨论】:

          【解决方案14】:
          const getOrdinalNum = (n) => n + (n > 0 ? ['th', 'st', 'nd', 'rd'][(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10] : '');
          

          【讨论】:

          • 虽然此代码可以回答问题,但提供有关 如何 和/或 为什么 解决问题的附加上下文将改善答案的长期价值。
          【解决方案15】:

          这是另一种选择。

          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 号

          【讨论】:

            【解决方案16】:

            我想为这个问题提供一个实用的答案来补充现有的答案:

            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(因为我们使用基于零的索引)决定的序数 mod 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
            

            【讨论】:

              【解决方案17】:

              我为我的东西制作的旧...

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

              【讨论】:

              • 添加一些关于上述代码的描述。它的帮助远不止一段代码。
              【解决方案18】:

              我为更大的数字和所有测试用例编写了这个函数

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

              【讨论】:

                【解决方案19】:

                这是一种略有不同的方法(我认为其他答案不会这样做)。我不确定我是喜欢它还是讨厌它,但它确实有效!

                export function addDaySuffix(day: number) { 
                  const suffixes =
                      '  stndrdthththththththththththththththththstndrdthththththththst';
                    const startIndex = day * 2;
                
                    return `${day}${suffixes.substring(startIndex, startIndex + 2)}`;
                  }
                

                【讨论】:

                  【解决方案20】:

                  我强烈推荐这个,阅读起来超级简单明了。希望对您有所帮助?

                  • 它避免使用负整数,即小于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
                  

                  【讨论】:

                    【解决方案21】:

                    这是给 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
                    

                    +be 数字的另一个选项是:

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

                    还要摆脱序数前缀,只需使用这些:

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

                    随意修改以满足您的需要

                    【讨论】:

                    • 这个答案的一部分只是从this answer复制而来,没有信用。
                    【解决方案22】:

                    &lt;p&gt;31&lt;sup&gt;st&lt;/sup&gt; March 2015&lt;/p&gt;

                    你可以使用

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

                    用于定位后缀

                    【讨论】:

                    • 这不是 OP 所要求的
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-01-07
                    • 1970-01-01
                    • 2015-10-11
                    • 2021-04-07
                    相关资源
                    最近更新 更多