Qual método na classe String retorna apenas os primeiros N caracteres?

184

Gostaria de escrever um método de extensão para a Stringclasse, para que, se a string de entrada for maior que o comprimento fornecido N, apenas os primeiros Ncaracteres sejam exibidos.

Veja como fica:

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

Qual String.*()método posso usar para obter apenas os primeiros Ncaracteres str?

Richard77
fonte

Respostas:

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
fonte
6
O Math.Min é necessário? Eu pensei que o Substring sabia que se o segundo parâmetro fosse maior que o comprimento, ele apenas conectaria o comprimento?
Martin
12
Eu acredito que é: System.String.InternalSubStringWithChecks jogaria ArgumentOutOfRange.
Paul Ruane
2
@ Martin: não que eu possa ver, startIndex > (this.Length - length)joga um ArgumentOutOfRangeException.
user7116
2
Eu sugeriria verificar se, Math.Min(str.Length, maxLength) == str.Lengthno caso de você acabar criando uma string desnecessária para retornar "os primeiros str.Length caracteres de str", mas o Substring verifica isso para você e o faz apenas return thisse você tiver solicitado a string inteira.
stevemegson
2
Se você deseja que o método de extensão funcione em cadeias potencialmente nulas ... retorne str? .Substring (0, Math.Min (str.Length, maxLength));
ihake
62
string truncatedToNLength = new string(s.Take(n).ToArray());  

Essa solução tem um pequeno bônus, pois se n for maior que s.Length, ainda assim fará a coisa certa.

Matt Greer
fonte
9
Sim, mas usando o Linq para truncar uma string? Esteja ciente de que o desempenho será muito ruim se usado muitas vezes, como em um loop. Não faça isso como uma questão de hábito
ErikE
31

Você pode usar o LINQ str.Take(n)ou str.SubString(0, n), onde o último lançará uma ArgumentOutOfRangeExceptionexceção para n > str.Length.

Mente que a versão LINQ retorna um IEnumerable<char>, então você teria que converter a IEnumerable<char>para string: new string(s.Take(n).ToArray()).

theburningmonk
fonte
10
Não use o Linq para truncar seqüências de caracteres. Isso é ridículo.
ErikE 14/05
17

Sempre que tenho que fazer manipulações de strings em C #, sinto falta do bom Lefte velho Rightfunções do Visual Basic, que são muito mais simples de usar do que Substring.

Portanto, na maioria dos meus projetos em C #, crio métodos de extensão para eles:

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:
A Math.Minpeça está lá porque Substringlança um ArgumentOutOfRangeExceptionquando o comprimento da string de entrada é menor que o tamanho solicitado, como já mencionado em alguns comentários nas respostas anteriores.

Uso:

string longString = "Long String";

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

// returns "Long String";
string left2 = longString.Left(100);
Christian Specht
fonte
Eu gosto disso, mas se a string fosse menor que o comprimento especificado, ela não acrescentaria espaços. 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
strprecisa ser verificado para nulo
liviriniu
14

Simplesmente:

public static String Truncate(String input,int maxLength)
{
   if(input.Length > maxLength)
      return input.Substring(0,maxLength);
   return input;
}
Majid
fonte
7
public static string TruncateLongString(this string str, int maxLength)
{
    return str.Length <= maxLength ? str : str.Remove(maxLength);
}
Kbrimington
fonte
1
Além disso, nota que você poderia também fazer o método de extensão nulo-safe, alterando a condição destr == null || str.Length <= maxLength
kbrimington
6
Para quem quer saber se é Removeou Substringnão melhor, não há diferença. Remove(maxLength)apenas chama Substring(0,maxLength)depois de um pouco de verificação de limites. O que você prefere depende se você considera o truncamento como "pegue os primeiros caracteres maxLength" ou "jogue fora tudo depois dos caracteres maxLength". Claro, são realmente as duas coisas, então depende de você.
stevemegson
5

se estamos falando de validações, também porque não verificamos entradas de sequência nula. Alguma razão específica?

Acho que ajuda abaixo, uma vez que IsNullOrEmpty é um método definido pelo sistema e operadores ternários têm complexidade ciclomática = 1 enquanto if () {} else {} tem o valor 2.

    public static string Truncate(string input, int truncLength)
    {
        return (!String.IsNullOrEmpty(input) && input.Length >= truncLength)
                   ? input.Substring(0, truncLength)
                   : input;
    }
sunnytyra
fonte
qual é o problema da complexidade ciclomática 2?
Muflix 5/10
1

Eu adicionei isso no meu projeto apenas porque, onde estou usando, há uma grande chance de ser usado em loops, em um projeto hospedado on-line, portanto, eu não queria nenhuma falha se pudesse gerenciá-lo. O comprimento se encaixa em uma coluna que tenho. É C # 7

Apenas uma linha:

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

O método .NET Substring está cheio de perigos. Desenvolvi métodos de extensão que lidam com uma grande variedade de cenários. O bom é que ele preserva o comportamento original, mas quando você adiciona um parâmetro "true" adicional, ele recorre ao método de extensão para manipular a exceção e retorna os valores mais lógicos, com base no índice e no comprimento. Por exemplo, se o comprimento for negativo e conta para trás. Você pode ver os resultados do teste com grande variedade de valores no violino em: https://dotnetfiddle.net/m1mSH9 . Isso lhe dará uma idéia clara de como ele resolve substrings.

Eu sempre adiciono esses métodos a todos os meus projetos e nunca preciso me preocupar com quebra de código, porque algo mudou e o índice é inválido. Abaixo está o 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));
    }

Eu escrevi sobre isso em maio de 2010 em: http://jagdale.blogspot.com/2010/05/substring-extension-method-that-does.html

Vijay Jagdale
fonte
0

Parcialmente para fins de resumo (excluindo a solução LINQ), eis duas linhas que abordam a int maxLengthressalva de permitir valores negativos e também o caso da cadeia nula:

  1. O Substringcaminho ( da resposta de Paul Ruane ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Substring(0, Math.Min(s.Length, (int)maxLength));
  1. O Removecaminho ( da resposta de kbrimington ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Length > maxLength ? s.Remove((int)maxLength) : s;
liviriniu
fonte
-1
substring(int startpos, int lenght);
Tokk
fonte
-4

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

Jagan
fonte
4
Diferentemente da resposta aceita, isso pode resultar em erros de índice fora dos limites.
Servy