在c#中有一个简单的方法来创建一个数字的序数吗?例如:

1返回第1位 2返回第2 3返回第3 等

这是否可以通过String.Format()来完成,或者是否有可用的函数来完成?


当前回答

又一个1号班轮。

public static string Ordinal(this int n)
{    
 return n + (new [] {"st","nd","rd" }.ElementAtOrDefault((((n + 90) % 100 - 10) % 10 - 1)) ?? "th");
}

其他回答

我使用的另一种替代方法是基于所有其他建议,但不需要特殊的大小写:

public static string DateSuffix(int day)
{
    if (day == 11 | day == 12 | day == 13) return "th";
    Math.DivRem(day, 10, out day);
    switch (day)
    {
        case 1:
            return "st";
        case 2:
            return "nd";
        case 3:
            return "rd";
        default:
            return "th";
    }
}

你得自己动手了。在我的脑海中:

public static string Ordinal(this int number)
{
  var work = number.ToString();
  if ((number % 100) == 11 || (number % 100) == 12 || (number % 100) == 13)
    return work + "th";
  switch (number % 10)
  {
    case 1: work += "st"; break;
    case 2: work += "nd"; break;
    case 3: work += "rd"; break;
    default: work += "th"; break;
  }
  return work;
}

你可以这样做

Console.WriteLine(432.Ordinal());

针对11/12/13例外进行了编辑。我确实从我的头顶说过:-)

为1011编辑-其他人已经修复了这个问题,只是想确保其他人不会抓取这个错误的版本。

Humanizer nuget包将为您提供帮助方法。免责声明,我是这个项目的贡献者。

Ordinalize将一个数字转换为一个序数字符串,用于表示在一个有序序列中的位置,例如1st, 2nd, 3rd, 4th:

1.Ordinalize() => "1st"
5.Ordinalize() => "5th"

你也可以对数字字符串调用Ordinalize函数,得到相同的结果:"21".Ordinalize() => "21st"

Ordinalize也支持两种形式的语法性别。 您可以将参数传递给Ordinalize,以指定数字应该以哪种性别输出。 可能的值为GrammaticalGender。男性,GrammaticalGender。女性和语法性别。中性:

// for Brazilian Portuguese locale
1.Ordinalize(GrammaticalGender.Masculine) => "1º"
1.Ordinalize(GrammaticalGender.Feminine) => "1ª"
1.Ordinalize(GrammaticalGender.Neuter) => "1º"
"2".Ordinalize(GrammaticalGender.Masculine) => "2º"
"2".Ordinalize(GrammaticalGender.Feminine) => "2ª"
"2".Ordinalize(GrammaticalGender.Neuter) => "2º"

显然,这只适用于某些文化。对于其他人来说,通过或不通过性别对结果没有任何影响。

此外,Ordinalize支持某些区域性应用的变体,这取决于序数在句子中的位置。 使用参数wordForm来获得一个或另一个结果。取值包括:WordForm。缩写和词形式。 你可以结合wordForm参数和性别参数,但是当它不适用时传入这个参数不会对结果产生任何影响。

// Spanish locale
1.Ordinalize(WordForm.Abbreviation) => "1.er" // As in "Vivo en el 1.er piso"
1.Ordinalize(WordForm.Normal) => "1.º" // As in "He llegado el 1º"
"3".Ordinalize(GrammaticalGender.Feminine, WordForm.Abbreviation) => "3.ª"
"3".Ordinalize(GrammaticalGender.Feminine, WordForm.Normal) => "3.ª"
"3".Ordinalize(GrammaticalGender.Masculine, WordForm.Abbreviation) => "3.er"
"3".Ordinalize(GrammaticalGender.Masculine, WordForm.Normal) => "3.º"

如果您想深入了解,请检查这些测试用例:OrdinalizeTests.cs

public static string OrdinalSuffix(int ordinal)
{
    //Because negatives won't work with modular division as expected:
    var abs = Math.Abs(ordinal); 

    var lastdigit = abs % 10; 

    return 
        //Catch 60% of cases (to infinity) in the first conditional:
        lastdigit > 3 || lastdigit == 0 || (abs % 100) - lastdigit == 10 ? "th" 
            : lastdigit == 1 ? "st" 
            : lastdigit == 2 ? "nd" 
            : "rd";
}

本页为您提供了所有自定义数字格式规则的完整列表:

自定义数字格式字符串

如你所见,这里没有关于序数的内容,所以不能使用String.Format。然而,编写一个函数来实现它并不难。

public static string AddOrdinal(int num)
{
    if( num <= 0 ) return num.ToString();

    switch(num % 100)
    {
        case 11:
        case 12:
        case 13:
            return num + "th";
    }
    
    switch(num % 10)
    {
        case 1:
            return num + "st";
        case 2:
            return num + "nd";
        case 3:
            return num + "rd";
        default:
            return num + "th";
    }
}

更新:从技术上讲,序数不存在<= 0,所以我更新了上面的代码。还删除了多余的ToString()方法。

还要注意,这不是国际化的。我不知道其他语言中的序数是什么样子。