Я хочу взять целое число и получить его порядковый номер, т.е.:
1 -> "First"
2 -> "Second"
3 -> "Third"
...
Я хочу взять целое число и получить его порядковый номер, т.е.:
1 -> "First"
2 -> "Second"
3 -> "Third"
...
Если вы в порядке с "1-м", "2-м", "3-м" и т.д., вот какой-то простой код, который будет корректно обрабатывать любое целое число:
public static String ordinal(int i) {
String[] sufixes = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
switch (i % 100) {
case 11:
case 12:
case 13:
return i + "th";
default:
return i + sufixes[i % 10];
}
}
Здесь несколько тестов для случаев краев:
public static void main(String[] args) {
int[] edgeCases = { 0, 1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 100, 101, 102, 103, 104, 111, 112, 113, 114 };
for (int edgeCase : edgeCases) {
System.out.println(ordinal(edgeCase));
}
}
Вывод:
0th
1st
2nd
3rd
4th
5th
10th
11th
12th
13th
14th
20th
21st
22nd
23rd
24th
100th
101st
102nd
103rd
104th
111th
112th
113th
114th
Используя отличный ICU4J (там также отличная версия C), вы также можете сделать это и получить Ординалы как простые слова;
RuleBasedNumberFormat nf = new RuleBasedNumberFormat(Locale.UK, RuleBasedNumberFormat.SPELLOUT);
for(int i = 0; i <= 30; i++)
{
System.out.println(i + " -> "+nf.format(i, "%spellout-ordinal"));
}
например, производит
0 -> zeroth
1 -> first
2 -> second
3 -> third
4 -> fourth
5 -> fifth
6 -> sixth
7 -> seventh
8 -> eighth
9 -> ninth
10 -> tenth
11 -> eleventh
12 -> twelfth
13 -> thirteenth
14 -> fourteenth
15 -> fifteenth
16 -> sixteenth
17 -> seventeenth
18 -> eighteenth
19 -> nineteenth
20 -> twentieth
21 -> twenty-first
22 -> twenty-second
23 -> twenty-third
24 -> twenty-fourth
25 -> twenty-fifth
26 -> twenty-sixth
27 -> twenty-seventh
28 -> twenty-eighth
29 -> twenty-ninth
30 -> thirtieth
Другое решение
public static String ordinal(int i) {
int mod100 = i % 100;
int mod10 = i % 10;
if(mod10 == 1 && mod100 != 11) {
return i + "st";
} else if(mod10 == 2 && mod100 != 12) {
return i + "nd";
} else if(mod10 == 3 && mod100 != 13) {
return i + "rd";
} else {
return i + "th";
}
}
Pro: не требует инициализации массива (меньше мусора)
Con: не однострочный...
Вот код для такого преобразования и вот еще один. И посмотрите на это ответы Как преобразовать число в слова в java
В 1 строке:
public static String ordinal(int i) {
return i % 100 == 11 || i % 100 == 12 || i % 100 == 13 ? i + "th" : i + new String[]{"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"}[i % 10];
}
Я выяснил, как сделать это на Android довольно простым способом. Все, что вам нужно сделать, это добавить зависимость в файл app
build.gradle
:
implementation "com.ibm.icu:icu4j:53.1"
Затем создайте этот метод:
Котлин:
fun Number?.getOrdinal(): String? {
if (this == null) {
return null
}
val format = "{0,ordinal}"
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
android.icu.text.MessageFormat.format(format, this)
} else {
com.ibm.icu.text.MessageFormat.format(format, this)
}
}
Ява:
public static String getNumberOrdinal(Number number) {
if (number == null) {
return null;
}
String format = "{0,ordinal}";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return android.icu.text.MessageFormat.format(format, number);
} else {
return com.ibm.icu.text.MessageFormat.format(format, number);
}
}
Затем вы можете просто использовать его так:
Котлин:
val ordinal = 2.getOrdinal()
Ява:
String ordinal = getNumberOrdinal(2)
Как это работает
Начиная с Android N (API 24), Android использует icu.text
вместо обычного java.text
(подробнее здесь), который уже содержит интернационализированную реализацию для порядковых номеров. Таким образом, решение, очевидно, простое - добавить библиотеку icu4j
в проект и использовать его в версиях под Nougat
Богемианский ответ очень хорош, но я рекомендую улучшить обработку ошибок. Если исходная версия ординала, если вы укажете отрицательное целое число, будет выбрано ArrayIndexOutOfBoundsException. Я думаю, что моя версия ниже ясна. Я надеюсь, что junit также полезен, поэтому нет необходимости визуально проверять вывод.
public class FormattingUtils {
/**
* Return the ordinal of a cardinal number (positive integer) (as per common usage rather than set theory).
* {@link http://stackoverflow.com/questions/6810336/is-there-a-library-or-utility-in-java-to-convert-an-integer-to-its-ordinal}
*
* @param i
* @return
* @throws {@code IllegalArgumentException}
*/
public static String ordinal(int i) {
if (i < 0) {
throw new IllegalArgumentException("Only +ve integers (cardinals) have an ordinal but " + i + " was supplied");
}
String[] sufixes = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
switch (i % 100) {
case 11:
case 12:
case 13:
return i + "th";
default:
return i + sufixes[i % 10];
}
}
}
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class WhenWeCallFormattingUtils_Ordinal {
@Test
public void theEdgeCasesAreCovered() {
int[] edgeCases = { 0, 1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 100, 101, 102, 103, 104, 111, 112,
113, 114 };
String[] expectedResults = { "0th", "1st", "2nd", "3rd", "4th", "5th", "10th", "11th", "12th", "13th", "14th",
"20th", "21st", "22nd", "23rd", "24th", "100th", "101st", "102nd", "103rd", "104th", "111th", "112th",
"113th", "114th" };
for (int i = 0; i < edgeCases.length; i++) {
assertThat(FormattingUtils.ordinal(edgeCases[i])).isEqualTo(expectedResults[i]);
}
}
@Test(expected = IllegalArgumentException.class)
public void supplyingANegativeNumberCausesAnIllegalArgumentException() {
FormattingUtils.ordinal(-1);
}
}
В Scala для изменения
List(1, 2, 3, 4, 5, 10, 11, 12, 13, 14 , 19, 20, 23, 33, 100, 113, 123, 101, 1001, 1011, 1013, 10011) map {
case a if (a % 10) == 1 && (a % 100) != 11 => a + "-st"
case b if (b % 10) == 2 && (b % 100) != 12 => b + "-nd"
case c if (c % 10) == 3 && (c % 100) != 13 => c + "-rd"
case e => e + "-th"
} foreach println
public static String getOrdinalFor(int value) {
int tenRemainder = value % 10;
switch (tenRemainder) {
case 1:
return value+"st";
case 2:
return value+"nd";
case 3:
return value+"rd";
default:
return value+"th";
}
}
Я получил длинную, сложную, но понятную концепцию
private static void convertMe() {
Scanner in = new Scanner(System.in);
try {
System.out.println("input a number to convert: ");
int n = in.nextInt();
String s = String.valueOf(n);
//System.out.println(s);
int len = s.length() - 1;
if (len == 0){
char lastChar = s.charAt(len);
if (lastChar == '1'){
System.out.println(s + "st");
} else if (lastChar == '2') {
System.out.println(s + "nd");
} else if (lastChar == '3') {
System.out.println(s + "rd");
} else {
System.out.println(s + "th");
}
} else if (len > 0){
char lastChar = s.charAt(len);
char preLastChar = s.charAt(len - 1);
if (lastChar == '1' && preLastChar != '1'){ //not ...11
System.out.println(s + "st");
} else if (lastChar == '2' && preLastChar != '1'){ //not ...12
System.out.println(s + "nd");
} else if (lastChar == '3' && preLastChar != '1'){ //not ...13
System.out.println(s + "rd");
} else {
System.out.println(s + "th");
}
}
} catch(InputMismatchException exception){
System.out.println("invalid input");
}
}
Лучший и простой способ, здесь мы идем:
import java.util.*;
public class Numbers
{
public final static String print(int num)
{
num = num%10;
String str = "";
switch(num)
{
case 1:
str = "st";
break;
case 2:
str = "nd";
break;
case 3:
str = "rd";
break;
default:
str = "th";
}
return str;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
System.out.print("Enter a number: ");
int number = sc.nextInt();
System.out.print(number + print(number));
}
}
private static String getOrdinalIndicator(int number) {
int mod = number;
if (number > 13) {
mod = number % 10;
}
switch (mod) {
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}