有没有一种简单的方法可以在C#中创建序数?
在C中,有没有一种简单的方法可以为数字创建序数?例如:
- 1返回第一
- 2返回第二
- 3返回3rd
- ...等等
可以通过String.Format()完成此操作,还是可以使用任何函数?
解决方案
回答
我们必须自己动手。从我的头顶:
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版进行了编辑-其他人已经解决了此问题,只想确保其他人不会抓住此错误的版本。
回答
该页面为我们提供了所有自定义数字格式设置规则的完整列表:
http://msdn.microsoft.com/zh-CN/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()方法。
另请注意,这不是国际化的。我不知道其他语言的序号是什么样子。
回答
我宁愿喜欢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; } }
回答
尽管我还没有对此进行基准测试,但是我们应该能够避免所有有条件的case语句,从而获得更好的性能。
这是java,但是对Cis来说却是一个琐碎的移植:
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语句解决方案那样可读。
回答
记住国际化!
这里的解决方案仅适用于英语。如果我们需要支持其他语言,事情会变得复杂得多。
例如,在西班牙语中," 1st"将被写为" 1.o"," 1.a"," 1.os"或者" 1.as",具体取决于我们要计数的是男性,女性还是复数形式!
因此,如果软件需要支持其他语言,请尝试避免使用普通字符。
回答
我的Jesse版本的Stu版本和samjudson版本的:)
包含的单元测试表明,当数字<1时,可接受的答案不正确
/// <summary> /// Get the ordinal value of positive integers. /// </summary> /// <remarks> /// 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 /// </remarks> /// <param name="number">The number.</param> /// <returns>Ordinal value of positive integers, or <see cref="int.ToString"/> if less than 1.</returns> 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()); }