¿Qué método en la clase String devuelve solo los primeros N caracteres?

184

Me gustaría escribir un método de extensión en la Stringclase para que si la cadena de entrada es más larga que la longitud proporcionada N, solo Nse mostrarán los primeros caracteres.

Así es como se ve:

public static string TruncateLongString(this string str, int maxLength)
{
    if (str.Length <= maxLength)
        return str;
    else
        //return the first maxLength characters                
}

¿Qué String.*()método puedo usar para obtener solo los primeros Ncaracteres str?

Richard77
fuente

Respuestas:

374
public static string TruncateLongString(this string str, int maxLength)
{
    if (string.IsNullOrEmpty(str))
        return str;
    return str.Substring(0, Math.Min(str.Length, maxLength));
}
Paul Ruane
fuente
66
¿Se necesita Math.Min? Pensé que Substring sabía que si el segundo parámetro era mayor que la longitud, ¿simplemente lo conectaba?
Martin
12
Creo que es: System.String.InternalSubStringWithChecks arrojaría ArgumentOutOfRange.
Paul Ruane
2
@ Martin: no es que pueda ver, startIndex > (this.Length - length)lanza un ArgumentOutOfRangeException.
user7116
2
Iba a sugerir verificar si Math.Min(str.Length, maxLength) == str.Lengthen caso de que termines creando una cadena innecesaria para devolver "la primera cadena. Caracteres largos de cadena", pero Substring hace esa verificación por ti y solo return thissi has pedido la cadena completa.
stevemegson
2
Si desea que el método de extensión funcione en cadenas potencialmente nulas ... devuelva str? .Substring (0, Math.Min (str.Length, maxLength));
Ihake
62
string truncatedToNLength = new string(s.Take(n).ToArray());  

Esta solución tiene una pequeña ventaja, ya que si n es mayor que s. Longitud, sigue haciendo lo correcto.

Matt Greer
fuente
9
Sí, pero ¿usando Linq para truncar una cadena? Solo tenga en cuenta que esto funcionará muy mal si se usa muchas veces, como en un bucle. No hagas esto por costumbre
ErikE
31

Puede usar LINQ str.Take(n)o str.SubString(0, n), donde este último arrojará una ArgumentOutOfRangeExceptionexcepción para n > str.Length.

Cuenta que la versión de LINQ devuelve una IEnumerable<char>, por lo que tendría que convertir el IEnumerable<char>a string: new string(s.Take(n).ToArray()).

themon ardiente
fuente
10
No use Linq para truncar cadenas. Eso es ridículo.
ErikE
17

Cada vez que tengo que hacer manipulaciones de cadenas en C #, echo de menos las funciones antiguas Lefty Rightde Visual Basic, que son mucho más simples de usar que Substring.

Entonces, en la mayoría de mis proyectos de C #, creo métodos de extensión para ellos:

public static class StringExtensions
{
    public static string Left(this string str, int length)
    {
        return str.Substring(0, Math.Min(length, str.Length));
    }

    public static string Right(this string str, int length)
    {
        return str.Substring(str.Length - Math.Min(length, str.Length));
    }
}

Nota:
La Math.Minparte está ahí porque Substringarroja un ArgumentOutOfRangeExceptioncuando la longitud de la cadena de entrada es menor que la longitud solicitada, como ya se mencionó en algunos comentarios en las respuestas anteriores.

Uso:

string longString = "Long String";

// returns "Long";
string left1 = longString.Left(4);

// returns "Long String";
string left2 = longString.Left(100);
Christian Specht
fuente
Me gusta esto, pero si la cadena fuera más corta que la longitud dada, no agregaría espacios. public static string Left(this string str, int length) { var Result = str.Substring(0, Math.Min(length, str.Length)); return (Result.Length < length) ? Result.PadRight(length) : Result; }
Grandizer
strnecesita ser verificado para nulo
liviriniu
14

Simplemente:

public static String Truncate(String input,int maxLength)
{
   if(input.Length > maxLength)
      return input.Substring(0,maxLength);
   return input;
}
Majid
fuente
7
public static string TruncateLongString(this string str, int maxLength)
{
    return str.Length <= maxLength ? str : str.Remove(maxLength);
}
kbrimington
fuente
1
Además, tenga en cuenta que también podría hacer que el método de extensión sea nulo seguro cambiando la condición astr == null || str.Length <= maxLength
kbrimington
66
Para cualquiera que se pregunte si Removeo Substringes mejor, no hay diferencia.Remove(maxLength)solo llama Substring(0,maxLength)después de un poco de verificación de límites. Lo que prefiera depende de si piensa en el truncamiento como "tomar los primeros caracteres maxLength" o "tirar todo después de los caracteres maxLength". Por supuesto, es realmente ambos, así que depende de ti.
stevemegson
5

si hablamos de validaciones también por qué no hemos verificado entradas de cadena nulas. ¿Alguna razón específica?

Creo que a continuación se muestra ayuda, ya que IsNullOrEmpty es un método definido por el sistema y los operadores ternarios tienen una complejidad ciclomática = 1, mientras que si () {} más {} tiene el valor 2.

    public static string Truncate(string input, int truncLength)
    {
        return (!String.IsNullOrEmpty(input) && input.Length >= truncLength)
                   ? input.Substring(0, truncLength)
                   : input;
    }
sunnytyra
fuente
¿Cuál es un problema con la complejidad ciclomática 2?
Muflix
1

Agregué esto en mi proyecto solo porque donde lo estoy usando es una alta probabilidad de que se use en bucles, en un proyecto alojado en línea, por lo tanto, no quería ningún bloqueo si pudiera administrarlo. La longitud se ajusta a una columna que tengo. Es C # 7

Solo una línea:

 public static string SubStringN(this string Message, int Len = 499) => !String.IsNullOrEmpty(Message) ? (Message.Length >= Len ? Message.Substring(0, Len) : Message) : "";
Richard Griffiths
fuente
0

El método de .NET Substring está lleno de peligros. Desarrollé métodos de extensión que manejan una amplia variedad de escenarios. Lo bueno es que conserva el comportamiento original, pero cuando agrega un parámetro "verdadero" adicional, recurre al método de extensión para manejar la excepción y devuelve los valores más lógicos, en función del índice y la longitud. Por ejemplo, si la longitud es negativa y cuenta hacia atrás. Puede ver los resultados de la prueba con una amplia variedad de valores en el violín en: https://dotnetfiddle.net/m1mSH9 . Esto le dará una idea clara de cómo resuelve las subcadenas.

Siempre agrego estos métodos a todos mis proyectos, y nunca tengo que preocuparme por la ruptura del código, porque algo cambió y el índice no es válido. Debajo está el código.

    public static String Substring(this String val, int startIndex, bool handleIndexException)
    {
        if (!handleIndexException)
        { //handleIndexException is false so call the base method
            return val.Substring(startIndex);
        }
        if (string.IsNullOrEmpty(val))
        {
            return val;
        }
        return val.Substring(startIndex < 0 ? 0 : startIndex > (val.Length - 1) ? val.Length : startIndex);
    }

    public static String Substring(this String val, int startIndex, int length, bool handleIndexException)
    {
        if (!handleIndexException)
        { //handleIndexException is false so call the base method
            return val.Substring(startIndex, length);
        }
        if (string.IsNullOrEmpty(val))
        {
            return val;
        }
        int newfrom, newlth, instrlength = val.Length;
        if (length < 0) //length is negative
        {
            newfrom = startIndex + length;
            newlth = -1 * length;
        }
        else //length is positive
        {
            newfrom = startIndex;
            newlth = length;
        }
        if (newfrom + newlth < 0 || newfrom > instrlength - 1)
        {
            return string.Empty;
        }
        if (newfrom < 0)
        {
            newlth = newfrom + newlth;
            newfrom = 0;
        }
        return val.Substring(newfrom, Math.Min(newlth, instrlength - newfrom));
    }

Escribí un blog sobre esto en mayo de 2010 en: http://jagdale.blogspot.com/2010/05/substring-extension-method-that-does.html

Vijay Jagdale
fuente
0

Parcialmente por el resumen (excluyendo la solución LINQ), aquí hay dos frases que abordan la int maxLengthadvertencia de permitir valores negativos y también el caso de una cadena nula:

  1. El Substringcamino (de la respuesta de Paul Ruane ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Substring(0, Math.Min(s.Length, (int)maxLength));
  1. El Removecamino (de la respuesta de kbrimington ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Length > maxLength ? s.Remove((int)maxLength) : s;
liviriniu
fuente
-1
substring(int startpos, int lenght);
Tokk
fuente
-4

string.Substring (0, n); // 0 - índice de inicio yn - número de caracteres

Jagan
fuente
44
A diferencia de la respuesta aceptada, esto puede dar como resultado errores de índice fuera de límites.
Servy