Есть ли в.NET простой способ получить окончание чисел "st", "nd", "rd" и "th"?

Мне интересно, есть ли метод или строка формата, которую мне не хватает в.NET для преобразования следующего:

   1 to 1st
   2 to 2nd
   3 to 3rd
   4 to 4th
  11 to 11th
 101 to 101st
 111 to 111th

Эта ссылка содержит плохой пример базового принципа, связанного с написанием вашей собственной функции, но мне более любопытно, есть ли встроенные возможности, которые мне не хватает.

Решение

Ответ Скотта Хансельмана является общепринятым, потому что он отвечает на вопрос напрямую.

Для решения, однако, см. Этот отличный ответ.

11 ответов

Решение

Нет, в библиотеке базовых классов.NET нет встроенной возможности.

Эта функция намного проще, чем вы думаете. Хотя для этого уже может существовать функция.NET, следующая функция (написанная на PHP) выполняет свою работу. Не должно быть слишком сложно переносить его.

function ordinal($num) {
    $ones = $num % 10;
    $tens = floor($num / 10) % 10;
    if ($tens == 1) {
        $suff = "th";
    } else {
        switch ($ones) {
            case 1 : $suff = "st"; break;
            case 2 : $suff = "nd"; break;
            case 3 : $suff = "rd"; break;
            default : $suff = "th";
        }
    }
    return $num . $suff;
}

Просто, чисто, быстро

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

@nickf: вот функция PHP в C#:

public static string Ordinal(int number)
{
    string suffix = String.Empty;

    int ones = number % 10;
    int tens = (int)Math.Floor(number / 10M) % 10;

    if (tens == 1)
    {
        suffix = "th";
    }
    else
    {
        switch (ones)
        {
            case 1:
                suffix = "st";
                break;

            case 2:
                suffix = "nd";
                break;

            case 3:
                suffix = "rd";
                break;

            default:
                suffix = "th";
                break;
        }
    }
    return String.Format("{0}{1}", number, suffix);
}

Это уже было рассмотрено, но я не уверен, как с ним связаться. Вот фрагмент кода:

    public static string Ordinal(this int number)
    {
        var ones = number % 10;
        var tens = Math.Floor (number / 10f) % 10;
        if (tens == 1)
        {
            return number + "th";
        }

        switch (ones)
        {
            case 1: return number + "st";
            case 2: return number + "nd";
            case 3: return number + "rd";
            default: return number + "th";
        }
    }

К вашему сведению: это как метод расширения. Если ваша версия.NET меньше 3.5, просто удалите ключевое слово this

[РЕДАКТИРОВАТЬ]: Спасибо за указание, что это было неправильно, это то, что вы получаете за код копирования / вставки:)

Вот версия функции Microsoft SQL Server:

CREATE FUNCTION [Internal].[GetNumberAsOrdinalString]
(
    @num int
)
RETURNS nvarchar(max)
AS
BEGIN

    DECLARE @Suffix nvarchar(2);
    DECLARE @Ones int;  
    DECLARE @Tens int;

    SET @Ones = @num % 10;
    SET @Tens = FLOOR(@num / 10) % 10;

    IF @Tens = 1
    BEGIN
        SET @Suffix = 'th';
    END
    ELSE
    BEGIN

    SET @Suffix = 
        CASE @Ones
            WHEN 1 THEN 'st'
            WHEN 2 THEN 'nd'
            WHEN 3 THEN 'rd'
            ELSE 'th'
        END
    END

    RETURN CONVERT(nvarchar(max), @num) + @Suffix;
END

Я знаю, что это не ответ на вопрос OP, но, поскольку я нашел полезным поднять функцию SQL Server из этого потока, вот эквивалент Delphi (Pascal):

function OrdinalNumberSuffix(const ANumber: integer): string;
begin
  Result := IntToStr(ANumber);
  if(((Abs(ANumber) div 10) mod 10) = 1) then // Tens = 1
    Result := Result + 'th'
  else
    case(Abs(ANumber) mod 10) of
      1: Result := Result + 'st';
      2: Result := Result + 'nd';
      3: Result := Result + 'rd';
      else
        Result := Result + 'th';
    end;
end;

Имеет ли смысл..., -1-е, 0-е?

Еще один аромат:

/// <summary>
/// Extension methods for numbers
/// </summary>
public static class NumericExtensions
{
    /// <summary>
    /// Adds the ordinal indicator to an integer
    /// </summary>
    /// <param name="number">The number</param>
    /// <returns>The formatted number</returns>
    public static string ToOrdinalString(this int number)
    {
        // Numbers in the teens always end with "th"

        if((number % 100 > 10 && number % 100 < 20))
            return number + "th";
        else
        {
            // Check remainder

            switch(number % 10)
            {
                case 1:
                    return number + "st";

                case 2:
                    return number + "nd";

                case 3:
                    return number + "rd";

                default:
                    return number + "th";
            }
        }
    }
}
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";
}
else if (choice=='q')
{
    qtr++;

    switch (qtr)
    {
        case(2): strcpy(qtrs,"nd");break;
        case(3):
        {
           strcpy(qtrs,"rd");
           cout<<"End of First Half!!!";
           cout<<" hteam "<<"["<<hteam<<"] "<<hs;
           cout<<" vteam "<<" ["<<vteam;
           cout<<"] ";
           cout<<vs;dwn=1;yd=10;

           if (beginp=='H') team='V';
           else             team='H';
           break;
       }
       case(4): strcpy(qtrs,"th");break;

Я думаю, что получить порядковый суффикс сложно... вам нужно написать функцию, которая использует переключатель для проверки чисел и добавления суффикса.

У языка нет причин предоставлять это внутренне, особенно когда это зависит от конкретной локали.

Вы можете сделать немного лучше, чем эта ссылка, когда дело доходит до объема кода, который нужно написать, но для этого нужно написать функцию...

Другие вопросы по тегам