当前位置:  开发笔记 > 编程语言 > 正文

有没有简单的方法在C#中创建序数?

如何解决《有没有简单的方法在C#中创建序数?》经验,为你挑选了7个好方法。

有没有在C#一个简单的方法来创建序数为多少?例如:

1返回1st

2返回第2

3返回第3

...等等

这可以通过String.Format()或有任何功能来完成吗?



1> samjudson..:

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

http://msdn.microsoft.com/en-us/library/0c899ak8.aspx

正如你所看到的那样,没有关于序数的内容,因此无法使用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()方法.

另请注意,这不是国际化的.我不知道其他语言的序数是什么样的.


忘了'11日,12日13'......应该是一个面试问题.:-)
Assert.AreEqual("0",AddOrdinal(0)); 见http://www.wisegeek.com/what-is-an-ordinal-number.htm
使用扩展方法(或其他任何方法 - 请参阅@Stu的答案)在这里工作得很好.@Si,如果需要,添加该条件将非常容易.
是的,程序员很奇怪;)
@IanWarburton没有冗余,因为将仅命中单个return语句。如果您对答案不满意,请提供您自己的答案,并向我们显示“正确”的方法,以及这样做的重要性。

2> roomaroo..:

记住国际化!

这里的解决方案仅适用于英语.如果您需要支持其他语言,事情会变得复杂得多.

例如,在西班牙语中,"1st"将被写为"1.o","1.a","1.os"或"1.as",具体取决于您所计算的事物是男性,女性还是复数!

因此,如果您的软件需要支持不同的语言,请尽量避免使用序数.


这解释了为什么.NET团队没有将其添加到DateTime格式化器中
@Andomar:"前2位读者"=>意大利语(我想也是西班牙语)"first"在这里是复数.所以你有奇异的男性化,单一的女性化,多元化的男性化,多元化的女性化; 也许某些语言也有一个中性的案例(区别于男/动物)
优点,很容易忘记.
如果你们都使用了".",那将非常简单.顺序的字符,就像我们在德语中那样))))1.2. 3. 4. 5.,等等.虽然算法会更有意思,如果有人写出数字,并且必须在4中附加变形除了12种不同组合的单数和复数个案外,还有3种不同文章的语法案例.想想看,俄罗斯人不要再有2个,加上vocativ,有些北欧语言有15个,我想.我很高兴看到.NET中的实现.
1号怎么能复数?
也就是说,您不必避免相关:将它们包含在本地化中,一旦您知道可能面临的所有情况,或(让您的客户)接受一些限制.

3> si618..:

我的版本的Jesse版本的Stu和samjudson的版本:)

包含单元测试,以显示数字<1时接受的答案不正确

    /// 
    /// Get the ordinal value of positive integers.
    /// 
    /// 
    /// Only works for english-based cultures.
    /// Code from: http://stackoverflow.com/questions/20156/is-there-a-quick-way-to-create-ordinals-in-c/31066#31066
    /// With help: http://www.wisegeek.com/what-is-an-ordinal-number.htm
    /// 
    /// The number.
    /// Ordinal value of positive integers, or  if less than 1.
    public static string Ordinal(this int number)
    {
        const string TH = "th";
        string s = number.ToString();

        // Negative and zero have no ordinal representation
        if (number < 1)
        {
            return s;
        }

        number %= 100;
        if ((number >= 11) && (number <= 13))
        {
            return s + TH;
        }

        switch (number % 10)
        {
            case 1: return s + "st";
            case 2: return s + "nd";
            case 3: return s + "rd";
            default: return s + TH;
        }
    }

    [Test]
    public void Ordinal_ReturnsExpectedResults()
    {
        Assert.AreEqual("-1", (1-2).Ordinal());
        Assert.AreEqual("0", 0.Ordinal());
        Assert.AreEqual("1st", 1.Ordinal());
        Assert.AreEqual("2nd", 2.Ordinal());
        Assert.AreEqual("3rd", 3.Ordinal());
        Assert.AreEqual("4th", 4.Ordinal());
        Assert.AreEqual("5th", 5.Ordinal());
        Assert.AreEqual("6th", 6.Ordinal());
        Assert.AreEqual("7th", 7.Ordinal());
        Assert.AreEqual("8th", 8.Ordinal());
        Assert.AreEqual("9th", 9.Ordinal());
        Assert.AreEqual("10th", 10.Ordinal());
        Assert.AreEqual("11th", 11.Ordinal());
        Assert.AreEqual("12th", 12.Ordinal());
        Assert.AreEqual("13th", 13.Ordinal());
        Assert.AreEqual("14th", 14.Ordinal());
        Assert.AreEqual("20th", 20.Ordinal());
        Assert.AreEqual("21st", 21.Ordinal());
        Assert.AreEqual("22nd", 22.Ordinal());
        Assert.AreEqual("23rd", 23.Ordinal());
        Assert.AreEqual("24th", 24.Ordinal());
        Assert.AreEqual("100th", 100.Ordinal());
        Assert.AreEqual("101st", 101.Ordinal());
        Assert.AreEqual("102nd", 102.Ordinal());
        Assert.AreEqual("103rd", 103.Ordinal());
        Assert.AreEqual("104th", 104.Ordinal());
        Assert.AreEqual("110th", 110.Ordinal());
        Assert.AreEqual("111th", 111.Ordinal());
        Assert.AreEqual("112th", 112.Ordinal());
        Assert.AreEqual("113th", 113.Ordinal());
        Assert.AreEqual("114th", 114.Ordinal());
        Assert.AreEqual("120th", 120.Ordinal());
        Assert.AreEqual("121st", 121.Ordinal());
        Assert.AreEqual("122nd", 122.Ordinal());
        Assert.AreEqual("123rd", 123.Ordinal());
        Assert.AreEqual("124th", 124.Ordinal());
    }



4> Shahzad Qure..:

简单,干净,快捷

    private static string GetOrdinalSuffix(int num)
    {
        if (num.ToString().EndsWith("11")) return "th";
        if (num.ToString().EndsWith("12")) return "th";
        if (num.ToString().EndsWith("13")) return "th";
        if (num.ToString().EndsWith("1")) return "st";
        if (num.ToString().EndsWith("2")) return "nd";
        if (num.ToString().EndsWith("3")) return "rd";
        return "th";
    }

或者更好,作为一种扩展方法

public static class IntegerExtensions
{
    public static string DisplayWithSuffix(this int num)
    {
        if (num.ToString().EndsWith("11")) return num.ToString() + "th";
        if (num.ToString().EndsWith("12")) return num.ToString() + "th";
        if (num.ToString().EndsWith("13")) return num.ToString() + "th";
        if (num.ToString().EndsWith("1")) return num.ToString() + "st";
        if (num.ToString().EndsWith("2")) return num.ToString() + "nd";
        if (num.ToString().EndsWith("3")) return num.ToString() + "rd";
        return num.ToString() + "th";
    }
}

现在你可以打电话了

int a = 1;
a.DisplayWithSuffix(); 

甚至像直接一样

1.DisplayWithSuffix();



5> Stu..:

你必须自己动手.从我的头顶:

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

编辑于2013年12月12日例外.我从头顶说:-)

编辑为1011 - 其他人已经解决了这个问题,只是想确保其他人不会抓住这个不正确的版本.



6> Jesse C. Sli..:

我更喜欢Stu和samjudson解决方案中的元素,并将它们组合成我认为可用的组合:

    public static string Ordinal(this int number)
    {
        const string TH = "th";
        var s = number.ToString();

        number %= 100;

        if ((number >= 11) && (number <= 13))
        {
            return s + TH;
        }

        switch (number % 10)
        {
            case 1:
                return s + "st";
            case 2:
                return s + "nd";
            case 3:
                return s + "rd";
            default:
                return s + TH;
        }
    }


而且,如果TH的值发生变化,你就会被设定.
@Jesse - 你得到我的+1,但我不相信.NET以这种方式处理字符串,请参阅http://www.yoda.arachsys.com/csharp/strings.html#interning,我的阅读是每个参考到"th"字面值将引用相同的内存.但我同意DRY :)
像这样删除重复只会妨碍我的可读性,因此混淆"为什么TH?".我不认为DRY应该被解释为"删除所有重复,无论成本如何".

7> Ryan McGeary..:

虽然我尚未对此进行基准测试,但您应该能够通过避免所有条件语句来获得更好的性能.

这是java,但是C#的端口是微不足道的:

public class NumberUtil {
  final static String[] ORDINAL_SUFFIXES = {
    "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
  };

  public static String ordinalSuffix(int value) {
    int n = Math.abs(value);
    int lastTwoDigits = n % 100;
    int lastDigit = n % 10;
    int index = (lastTwoDigits >= 11 && lastTwoDigits <= 13) ? 0 : lastDigit;
    return ORDINAL_SUFFIXES[index];
  }

  public static String toOrdinal(int n) {
    return new StringBuffer().append(n).append(ordinalSuffix(n)).toString();
  }
}

注意,如果在紧密循环中生成大量序数,则条件的减少和数组查找的使用应该会加快性能.但是,我也承认这不像case语句解决方案那样可读.

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有