Quelle méthode de la classe String renvoie uniquement les N premiers caractères?

184

Je voudrais écrire une méthode d'extension à la Stringclasse afin que si la chaîne d'entrée est plus longue que la longueur fournie N, seul le premierN caractères doivent être affichés.

Voici à quoi cela ressemble:

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

Quelle String.*()méthode puis-je utiliser pour obtenir uniquement les premiers Ncaractères de str?

Richard77
la source

Réponses:

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
la source
6
Le Math.Min est-il nécessaire? Je pensais que Substring savait que si le deuxième paramètre était supérieur à la longueur, il se contentait de brancher la longueur?
Martin
12
Je crois que c'est: System.String.InternalSubStringWithChecks lancerait ArgumentOutOfRange.
Paul Ruane
2
@Martin: pas que je puisse voir, startIndex > (this.Length - length)lance un ArgumentOutOfRangeException.
user7116
2
J'allais suggérer de vérifier si Math.Min(str.Length, maxLength) == str.Lengthau cas où vous finiriez par créer une chaîne inutile pour renvoyer "les premiers caractères str.Length de str", mais Substring fait cette vérification pour vous et le fait simplement return thissi vous avez demandé la chaîne entière.
stevemegson
2
Si vous voulez que la méthode d'extension fonctionne sur des chaînes potentiellement nulles ... return str? .Substring (0, Math.Min (str.Length, maxLength));
ihake
62
string truncatedToNLength = new string(s.Take(n).ToArray());  

Cette solution a un petit avantage en ce que si n est supérieur à la longueur, elle fait toujours la bonne chose.

Matt Greer
la source
9
Ouais, mais utiliser Linq pour tronquer une chaîne? Sachez simplement que cela fonctionnera très mal s'il est utilisé plusieurs fois, par exemple dans une boucle. Ne faites pas cela par habitude
ErikE
31

Vous pouvez utiliser LINQ str.Take(n)ou str.SubString(0, n), où ce dernier lèvera une ArgumentOutOfRangeExceptionexception pourn > str.Length .

L' esprit que la version LINQ renvoie IEnumerable<char>, vous auriez donc avoir à convertir le IEnumerable<char>à string: new string(s.Take(n).ToArray()).

theburningmonk
la source
10
N'utilisez pas Linq pour tronquer des chaînes. C'est ridicule.
ErikE
17

Chaque fois que je dois faire des manipulations de chaînes en C #, je manque le bon vieux Leftet les Rightfonctions de Visual Basic, qui sont beaucoup plus simples à utiliser queSubstring .

Donc, dans la plupart de mes projets C #, je crée des méthodes d'extension pour eux:

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

Remarque:
la Math.Minpartie est là car Substringjette unArgumentOutOfRangeException lorsque la longueur de la chaîne d'entrée est inférieure à la longueur demandée, comme déjà mentionné dans certains commentaires sous les réponses précédentes.

Usage:

string longString = "Long String";

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

// returns "Long String";
string left2 = longString.Left(100);
Christian Specht
la source
J'aime ça, mais si la chaîne était plus courte que la longueur donnée, elle n'ajouterait pas d'espaces. 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
strdoit être vérifié pour null
liviriniu
14

Simplement:

public static String Truncate(String input,int maxLength)
{
   if(input.Length > maxLength)
      return input.Substring(0,maxLength);
   return input;
}
Majid
la source
7
public static string TruncateLongString(this string str, int maxLength)
{
    return str.Length <= maxLength ? str : str.Remove(maxLength);
}
Kbrimington
la source
1
Notez également que vous pouvez également rendre la méthode d'extension sûre pour les str == null || str.Length <= maxLength
valeurs
6
Pour quiconque se demande si c'est mieux Removeou Substringmieux, il n'y a pas de différence. Remove(maxLength)appelle juste Substring(0,maxLength)après un peu de vérification des limites. Ce que vous préférez dépend de si vous pensez que la troncature est "prendre les premiers caractères maxLength" ou "tout jeter après les caractères maxLength". Bien sûr, c'est vraiment les deux, c'est donc à vous de décider.
stevemegson
5

si nous parlons de validations, pourquoi nous n'avons pas vérifié les entrées de chaîne nulle. Des raisons spécifiques?

Je pense que ci-dessous aide car IsNullOrEmpty est une méthode définie par le système et les opérateurs ternaires ont une complexité cyclomatique = 1 tandis que if () {} else {} a la valeur 2.

    public static string Truncate(string input, int truncLength)
    {
        return (!String.IsNullOrEmpty(input) && input.Length >= truncLength)
                   ? input.Substring(0, truncLength)
                   : input;
    }
sunnytyra
la source
qu'est-ce qu'un problème avec la complexité cyclomatique 2?
Muflix
1

J'ai ajouté cela dans mon projet simplement parce que là où je l'utilise, il y a de fortes chances qu'il soit utilisé dans des boucles, dans un projet hébergé en ligne, donc je ne voulais pas de crash si je pouvais le gérer. La longueur correspond à une colonne que j'ai. C'est C # 7

Juste une ligne:

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

La méthode .NET Substring est lourde de risques. J'ai développé des méthodes d'extension qui gèrent une grande variété de scénarios. La bonne chose est qu'il préserve le comportement d'origine, mais lorsque vous ajoutez un paramètre supplémentaire "true", il recourt ensuite à la méthode d'extension pour gérer l'exception et renvoie les valeurs les plus logiques, basées sur l'index et la longueur. Par exemple, si la longueur est négative et compte à rebours. Vous pouvez consulter les résultats des tests avec une grande variété de valeurs sur le violon à l' adresse : https://dotnetfiddle.net/m1mSH9 . Cela vous donnera une idée claire de la façon dont il résout les sous-chaînes.

J'ajoute toujours ces méthodes à tous mes projets et je n'ai jamais à me soucier de la rupture de code, car quelque chose a changé et l'index est invalide. Ci-dessous le code.

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

J'ai blogué à ce sujet en mai 2010 à l' adresse : http://jagdale.blogspot.com/2010/05/substring-extension-method-that-does.html

Vijay Jagdale
la source
0

En partie à des fins de récapitulation (à l'exclusion de la solution LINQ), voici deux one-liners qui adressent la int maxLengthmise en garde d'autoriser des valeurs négatives et également le cas de la chaîne nulle:

  1. Le Substringchemin (d'après la réponse de Paul Ruane ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Substring(0, Math.Min(s.Length, (int)maxLength));
  1. Le Removechemin (d' après la réponse de Kbrimington ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Length > maxLength ? s.Remove((int)maxLength) : s;
liviriniu
la source
-1
substring(int startpos, int lenght);
Tokk
la source
-4

string.Substring (0, n); // 0 - index de départ et n - nombre de caractères

Jagan
la source
4
Contrairement à la réponse acceptée, cela peut entraîner des erreurs d'index hors limites.
Servy