2008-09-16 11 views
59

Me pregunto si hay una cadena de método o formato que me falta en .NET para convertir el siguiente:¿Hay alguna manera fácil en .NET de obtener las terminaciones "st", "nd", "rd" y "th" para los números?

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

This link tiene un mal ejemplo del principio básico implicado en la escritura de su propia función, pero tengo más curiosidad si me falta una capacidad incorporada.

Solución

respuesta de Scott Hanselman es la aceptada uno porque responde a la pregunta directamente.

Para una solución, consulte this great answer.

+3

Se llaman los números ordinales (1º, 2º, etc.) en lugar de los números cardinales (1,2,3, etc.), para tu información. – pc1oad1etter

+1

Esto fue respondido con bastante elegancia aquí: http://stackoverflow.com/questions/20156/ordinals-in-c# – Portman

+0

Sí, he notado su respuesta. –

Respuesta

53

No, no hay capacidad incorporada en .NET Base Class Library.

+8

Este es un comentario tardío, pero ¿hay algún plan para agregar esta capacidad al .NET BCL para formatear las fechas? – Breakskater

79

Es una función mucho más simple de lo que crees. Aunque puede existir una función .NET para esto, la siguiente función (escrita en PHP) hace el trabajo. No debería ser demasiado difícil trasladarlo.

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; 
} 
+0

¿Qué pasa con la localización? – macbirdie

+2

La localización significará que debe crear funciones separadas para cada idioma. En alemán, puedes agregar "ter", pero "1ter" "2ter" "3ter" se ve muy mal aunque sea gramaticalmente correcto. En francés, es un poco mejor, pero no hay una forma universal para cada idioma. –

+0

@Michael Stum: no estoy muy familiarizado con todos los formatos ordinales internacionales, pero ¿bastaría con una cadena de caracteres. Formato (resString, número)? ¿O algunos idiomas no combinan números con ixes ordinales (pre/suf)? –

12

Esto ya se ha cubierto, pero no estoy seguro de cómo vincularlo. Aquí está el código snippit:

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"; 
     } 
    } 

FYI: Esto es como un método de extensión. Si la versión de .NET es inferior a 3,5 acaba de quitar la palabra clave this

[EDIT]: Gracias por señalar que era incorrecto, eso es lo que obtienes por código de copiar/pegar :)

+4

No funciona. 1011% 10 == 1. 1011st es incorrecto. –

+0

+1 para el método de extensión –

+8

Me gusta cómo declaras las variables y nunca las utilizas. –

-6

Creo que el sufijo ordinal es difícil de conseguir ... básicamente tienes que escribir una función que use un interruptor para probar los números y agregar el sufijo.

No hay razón para que un idioma proporcione esto internamente, especialmente cuando es específico de la configuración regional.

Puede hacer un poco mejor que el enlace cuando se trata de la cantidad de código para escribir, pero hay que codificar una función para este ...

+1

Dadas todas las cadenas de localización de divisas, etc. parece un poco exagerado agregar el sufijo ordinal. –

54

@nickf: Esta es la función de PHP en 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); 
} 
+0

Ha gracias, estoy a punto de publicar el código que escribí. Tuyo supera al mío de todos modos con el bit String.Format, creo. –

+0

1) ¿Por qué la conversión a decimal? Un simple '(number/10)% 10' hace el truco. 2) ¿Por qué inicializas 'sufijo' a un valor que nunca se usará? – CodesInChaos

+0

@CodesInChaos: Sin la conversión a decimal, se obtiene un error de compilación: 'La llamada es ambigua entre los siguientes métodos o propiedades: 'System.Math.Floor (decimal)' y 'System.Math.Floor (double)' ' . Inicializar 'sufijo' a' String.Empty' es principalmente un hábito, pero también ayuda a evitar el uso accidental de '' errores de sufijo '' de variable local no asignada. –

-3
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; 
+1

vamos. ¿que estas escribiendo? No tiene nada que ver con mi pregunta. – santubangalore

8

Aquí hay una versión de Microsoft SQL Server Función:

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 
+0

¡Acabo de escribir esa función casi textualmente! Diferencias: master db, cast en lugar de convert, y uso indentado ligeramente diferente. Grandes mentes, supongo ... –

+0

+1 - Simplemente tuve la necesidad de una versión SQL - me salvó la escritura de un – HeavenCore

+0

Excelente, pero solo si estamos obteniendo de SQL. Pero en este caso estoy formateando una variable .Net DateTime. Pero esta función será inmensamente útil. – santubangalore

2

sé que esto no es una respuesta a La pregunta de la OP, sino porque he encontrado que es útil para levantar la función de SQL Server de este hilo, aquí es un Delphi (Pascal) equivalente:

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; 

hace ..., -1º, 0th sentido?

+0

Excelente respuesta. – santubangalore

50

simple, limpio, rápido

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"; 
    } 

O mejor aún, como un método de extensión

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"; 
    } 
} 

Ahora sólo puede llamar

int a = 1; 
a.DisplayWithSuffix(); 

o incluso tan directo como

1.DisplayWithSuffix(); 
+1

Probablemente la mejor respuesta aquí. –

+1

Creo que esta es la forma más limpia de hacerlo –

+1

Sin duda la mejor respuesta. Esto realmente se basa en el número como texto, en lugar de tratar de usar alguna fórmula matemática complicada. Así es exactamente como el cerebro humano lo resolvería, y eso es ideal. –

0

otro sabor:

/// <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"; 
      } 
     } 
    } 
} 
+0

Falla para '111' – CodesInChaos

+0

Buena captura. Fijo. –

+0

En realidad, es una buena respuesta. Pero es genérico, es decir, no específico de las fechas de un mes. Solo quise decir fechas. Así que por encima de 100 puede no ser aplicable. – santubangalore

0
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"; 
} 
Cuestiones relacionadas