Comment puis-je tronquer a.NET string?

je voudrais tronquer une chaîne de telle sorte que sa longueur ne soit pas plus longue qu'une valeur donnée. J'écris à une table de base de données et je veux m'assurer que les valeurs que j'écris respectent la contrainte du type de données de la colonne.

Par exemple, ce serait bien si je pouvais écrire ce qui suit:

string NormalizeLength(string value, int maxLength)
{
    return value.Substring(0, maxLength);
}

malheureusement, cela soulève une exception parce que maxLength dépasse généralement les limites de la chaîne de caractères value . Bien sûr, je pourrais écrire une fonction comme les suivantes, mais j'espérais que quelque chose comme cela existe déjà.

string NormalizeLength(string value, int maxLength)
{
    return value.Length <= maxLength ? value : value.Substring(0, maxLength);
} 

Où est L'insaisissable API qui effectue cette tâche? Est-il un?

316
demandé sur Mark Amery 2010-05-06 00:50:01

27 réponses

il n'y a pas de méthode Truncate() sur string, malheureusement. Vous devez écrire ce genre de logique vous-même. Ce que vous pouvez faire, cependant, c'est envelopper ceci dans une méthode d'extension afin que vous n'ayez pas à le dupliquer partout:

public static class StringExt
{
    public static string Truncate(this string value, int maxLength)
    {
        if (string.IsNullOrEmpty(value)) return value;
        return value.Length <= maxLength ? value : value.Substring(0, maxLength); 
    }
}

maintenant nous pouvons écrire:

var someString = "...";
someString = someString.Truncate(2);
482
répondu LBushkin 2014-01-20 21:12:53

Ou à la place de l'opérateur ternaire, vous pouvez utiliser les Mathématiques.min

public static class StringExt
{
    public static string Truncate( this string value, int maxLength )
    {
        if (string.IsNullOrEmpty(value)) { return value; }

        return value.Substring(0, Math.Min(value.Length, maxLength));
    }
}
96
répondu CaffGeek 2012-12-19 20:37:02

j'ai pensé que je voudrais jeter dans mon application depuis je crois qu'il couvre tous les cas qui ont été abordés par les autres et le fait de manière concise qui est encore lisible.

public static string Truncate(this string value, int maxLength)
{
    if (!string.IsNullOrEmpty(value) && value.Length > maxLength)
    {
        return value.Substring(0, maxLength);
    }

    return value;
}

cette solution s'appuie principalement sur le Ray's solution et ouvre la méthode pour une utilisation comme une méthode d'extension en utilisant le ce mot-clé tout comme LBushkin fait dans sa solution.

34
répondu jpierson 2018-01-31 14:39:44

vous pouvez utiliser LINQ... il élimine le besoin de vérifier la longueur de la chaîne. Certes peut-être pas le plus efficace, mais c'est amusant.

string result = string.Join("", value.Take(maxLength)); // .NET 4 Join

ou

string result = new string(value.Take(maxLength).ToArray());
27
répondu tames 2010-05-05 21:06:19

dans .NET 4.0 vous pouvez utiliser la méthode Take :

string.Concat(myString.Take(maxLength));

Non testé pour l'efficacité!

26
répondu Dylan Nicholson 2016-05-18 23:07:34

le Framework .NET a une API pour tronquer une chaîne de caractères comme celle-ci:

Microsoft.VisualBasic.Strings.Left(string, int);

mais dans une application C# app, vous préférerez probablement lancer votre propre application plutôt que de prendre une dépendance sur Microsoft.VisualBasic.dll, dont la principale raison d'être est la rétrocompatibilité.

12
répondu Joe 2012-11-08 14:46:43

parce que les tests de performance sont amusants: (en utilisant linqpad extension methods )

var val = string.Concat(Enumerable.Range(0, 50).Select(i => i % 10));

foreach(var limit in new[] { 10, 25, 44, 64 })
    new Perf<string> {
        { "newstring" + limit, n => new string(val.Take(limit).ToArray()) },
        { "concat" + limit, n => string.Concat(val.Take(limit)) },
        { "truncate" + limit, n => val.Substring(0, Math.Min(val.Length, limit)) },
        { "smart-trunc" + limit, n => val.Length <= limit ? val : val.Substring(0, limit) },
        { "stringbuilder" + limit, n => new StringBuilder(val, 0, Math.Min(val.Length, limit), limit).ToString() },
    }.Vs();

la méthode truncate était "significativement" plus rapide. # microoptimisation

Début

  • truncate10 5788 tiques écoulées (0,5788 ms) [in 10K reps, 5.788 E-05 ms per]
  • smart-trunc10 8206 tics écoulés (0,8206 ms) [in 10K répétitions, 8.206 E-05 ms par]
  • stringbuilder10 10557 tiques écoulé (1.0557 ms) [en 10K répétitions, 0.00010557 ms par]
  • concat10 45495 tiques écoulé (4.5495 ms) [en 10K répétitions, 0.00045495 ms par]
  • newstring10 72535 tiques écoulé (7.2535 ms) [en 10K répétitions, 0.00072535 ms par]

en Retard

  • truncate44 8835 tiques écoulé (0.8835 ms) [en 10K répétitions, 8.835 E-05 ms par]
  • stringbuilder44 13106 tiques écoulé (1.3106 ms) [en 10K répétitions, 0.00013106 ms par]
  • smart-trunc44 14821 tiques écoulé (1.4821 ms) [en 10K répétitions, 0.00014821 ms par]
  • newstring44 144324 tiques écoulé (14.4324 ms) [en 10K répétitions, 0.00144324 ms par]
  • concat44 174610 tiques écoulées (17.461 ms) [en 10K répétitions, 0.0017461 ms par]

Trop Long

  • smart-trunc64 6944 tiques écoulées (0,6944 ms) [in 10K reps, 6,944 E-05 ms per]
  • truncate64 7686 tiques écoulé (0.7686 ms) [en 10K répétitions, 7.686 E-05 ms par]
  • stringbuilder64 13314 tiques écoulé (1.3314 ms) [en 10K répétitions, 0.00013314 ms par]
  • newstring64 177481 tiques écoulé (17.7481 ms) [en 10K répétitions, 0.00177481 ms par]
  • concat64 241601 tiques écoulé (24.1601 ms) [en 10K répétitions, 0.00241601 ms par]
12
répondu drzaus 2017-09-06 15:12:14

semble que personne n'a encore posté ceci:

public static class StringExt
{
    public static string Truncate(this string s, int maxLength)
    {
        return s != null && s.Length > maxLength ? s.Substring(0, maxLength) : s;
    }
}

L'utilisation de l'opérateur & le rend légèrement meilleur que la réponse acceptée.

10
répondu Darren 2014-10-03 08:38:23

j'ai fait le mien dans une ligne comme celle-ci

value = value.Length > 1000 ? value.Substring(0, 1000) : value;
8
répondu SeanKPS 2017-05-23 16:30:48

une variante similaire avec l'opérateur de propagation nulle de C# 6

public static string Truncate(this string value, int maxLength)
{
    return value?.Length <= maxLength ? value : value?.Substring(0, maxLength);
}

veuillez noter que nous vérifions essentiellement si value est nul deux fois ici.

5
répondu Jamie Rees 2016-04-28 10:08:21

en Prenant @CaffGeek et de simplification:

public static string Truncate(this string value, int maxLength)
    {
        return string.IsNullOrEmpty(value) ? value : value.Substring(0, Math.Min(value.Length, maxLength));
    }
4
répondu Edwin Beltran 2013-03-26 18:56:39

Kndly noter que tronquer une corde ne signifie pas simplement justing couper une corde à une longueur spécifiée seul, mais doivent prendre soin de ne pas diviser le mot.

eg string: c'est une chaîne de test.

je veux le couper à 11 . Si nous utilisons l'une des méthodes indiquées ci-dessus, le résultat sera

c'est a te

ce n'est pas ce que nous voulons

le la méthode que j'utilise peut-être aussi pas si parfait, mais il peut gérer la plupart de la situation

public string CutString(string source, int length)
{
        if (source== null || source.Length < length)
        {
            return source;
        }
        int nextSpace = source.LastIndexOf(" ", length);
        return string.Format("{0}...", input.Substring(0, (nextSpace > 0) ? nextSpace : length).Trim());
} 
4
répondu Sen K. Mathew 2013-05-29 04:55:38

je sais que c'est une vieille question, mais voici une belle solution:

public static string Truncate(this string text, int maxLength, string suffix = "...")
{
    string str = text;
    if (maxLength > 0)
    {
        int length = maxLength - suffix.Length;
        if (length <= 0)
        {
            return str;
        }
        if ((text != null) && (text.Length > maxLength))
        {
            return (text.Substring(0, length).TrimEnd(new char[0]) + suffix);
        }
    }
    return str;
}

var myString = "hello world"
var myTruncatedString = myString.Truncate(4);

retourne: bonjour...

4
répondu nologo 2014-02-27 22:29:19

toujours pas de méthode tronquée en 2016 pour C # strings. Mais-En Utilisant La Syntaxe C# 6.0:

public static class StringExtension
{
  public static string Truncate(this string s, int max) 
  { 
    return s?.Length > max ? s.Substring(0, max) : s ?? throw new ArgumentNullException(s); 
  }
}

il fonctionne comme un charme:

"Truncate me".Truncate(8);
Result: "Truncate"
4
répondu Tobias Schiele 2016-10-28 14:50:07

Juste au cas où il n'y a pas assez de réponses, voici la mienne :)

public static string Truncate(this string str, 
                              int totalLength, 
                              string truncationIndicator = "")
{
    if (string.IsNullOrEmpty(str) || str.Length < totalLength) 
        return str;

    return str.Substring(0, totalLength - truncationIndicator.Length) 
           + truncationIndicator;
}

à utiliser:

"I use it like this".Truncate(5,"~")
3
répondu K. R. 2014-11-26 18:19:13

pourquoi pas:

string NormalizeLength(string value, int maxLength)
{
    //check String.IsNullOrEmpty(value) and act on it. 
    return value.PadRight(maxLength).Substring(0, maxLength);
}

, c'est-à-dire dans le cas value.Length < maxLength , des espaces au bout du coussinet ou tronquer l'excédent.

3
répondu Sri 2017-12-05 16:59:04

par souci de complexité, j'ajouterai ma version surchargée qui remplace les 3 derniers caractères par une ellipse par rapport au paramètre maxLength.

public static string Truncate(this string value, int maxLength, bool replaceTruncatedCharWithEllipsis = false)
{
    if (replaceTruncatedCharWithEllipsis && maxLength <= 3)
        throw new ArgumentOutOfRangeException("maxLength",
            "maxLength should be greater than three when replacing with an ellipsis.");

    if (String.IsNullOrWhiteSpace(value)) 
        return String.Empty;

    if (replaceTruncatedCharWithEllipsis &&
        value.Length > maxLength)
    {
        return value.Substring(0, maxLength - 3) + "...";
    }

    return value.Substring(0, Math.Min(value.Length, maxLength)); 
}
2
répondu SoftDev 2015-07-31 07:23:13

je préfère la réponse de jpierson, mais aucun des exemples que je peux voir ici ne traite un paramètre invalide maxLength, comme quand maxLength < 0.

choix serait soit gérer l'erreur dans un try/catch, clamper le paramètre maxlength min à 0, ou si maxLength est inférieur à 0 retourner une chaîne vide.

code non optimisé:

public string Truncate(this string value, int maximumLength)
{
    if (string.IsNullOrEmpty(value) == true) { return value; }
    if (maximumLen < 0) { return String.Empty; }
    if (value.Length > maximumLength) { return value.Substring(0, maximumLength); }
    return value;
}
1
répondu deegee 2013-03-23 19:36:34

voici un vb.net solution, notez que l'instruction if (bien que laid) améliore les performances car nous n'avons pas besoin de l'instruction substring lorsque la chaîne est déjà plus petite que maxlength... En faisant une extension de chaîne, il est facile à utiliser...

 <System.Runtime.CompilerServices.Extension()> _
    Public Function Truncate(String__1 As String, maxlength As Integer) As String
        If Not String.IsNullOrEmpty(String__1) AndAlso String__1.Length > maxlength Then
            Return String__1.Substring(0, maxlength)
        Else
            Return String__1
        End If
    End Function
1
répondu Jeroen Bom 2015-01-20 08:33:43

je sais qu'il y a déjà une tonne de réponses mais mon besoin était de garder le début et la fin de la corde intact mais raccourcir à la longueur max.

    public static string TruncateMiddle(string source)
    {
        if (String.IsNullOrWhiteSpace(source) || source.Length < 260) 
            return source;

        return string.Format("{0}...{1}", 
            source.Substring(0, 235),
            source.Substring(source.Length - 20));
    }

ceci est pour créer des URLs SharePoint qui ont une longueur maximale de 260 caractères.

Je n'ai pas fait de longueur un paramètre puisqu'il s'agit d'une constante 260. Je n'ai pas non plus fait de la première longueur de la sous-couche un paramètre parce que je veux qu'elle se casse à un point précis. Enfin, l' la deuxième sous-couche est la longueur du source-20 puisque je connais la structure du dossier.

cela pourrait facilement être adapté à vos besoins spécifiques.

1
répondu Paul Haan 2016-11-16 16:37:34

TruncateString

public static string _TruncateString(string input, int charaterlimit)
{
    int characterLimit = charaterlimit;
    string output = input;

    // Check if the string is longer than the allowed amount
    // otherwise do nothing
    if (output.Length > characterLimit && characterLimit > 0)
    {
        // cut the string down to the maximum number of characters
        output = output.Substring(0, characterLimit);
        // Check if the character right after the truncate point was a space
        // if not, we are in the middle of a word and need to remove the rest of it
        if (input.Substring(output.Length, 1) != " ")
        {
            int LastSpace = output.LastIndexOf(" ");

            // if we found a space then, cut back to that space
            if (LastSpace != -1)
            {
                output = output.Substring(0, LastSpace);
            }
        }
        // Finally, add the "..."
        output += "...";
    }
    return output;
}
0
répondu Sud 2016-01-25 09:23:15

je recommande d'utiliser la méthode du substrat pour la même fonctionnalité efficace.

    // Gets first n characters.
    string subString = inputString.Substring(0, n);

cela a l'avantage de vous permettre d'épiler votre chaîne de chaque côté ou même quelque part au milieu sans écrire des méthodes supplémentaires. Espérons que cela aide :)

pour référence supplémentaire: https://www.dotnetperls.com/substring

0
répondu SethMartn 2018-02-16 19:20:03

je sais qu'il y a déjà une tonne de réponses ici, mais c'est celle que j'ai choisie, qui gère à la fois les chaînes nulles et la situation où la longueur passée est négative:

public static string Truncate(this string s, int length)
{
    return string.IsNullOrEmpty(s) || s.Length <= length ? s 
        : length <= 0 ? string.Empty 
        : s.Substring(0, length);
}
0
répondu Ed B 2018-03-14 11:11:33

il n'y a rien dans .net pour cela que je sache - voici ma version qui ajoute"...":

public static string truncateString(string originalString, int length) {
  if (string.IsNullOrEmpty(originalString)) {
   return originalString;
  }
  if (originalString.Length > length) {
   return originalString.Substring(0, length) + "...";
  }
  else {
   return originalString;
  }
}
-1
répondu Ray 2010-05-05 20:57:13
public static string Truncate( this string value, int maxLength )
    {
        if (string.IsNullOrEmpty(value)) { return value; }

        return new string(value.Take(maxLength).ToArray());// use LINQ and be happy
    }
-1
répondu TapiocaCom 2013-05-17 20:19:21

Chaîne Tronquée

public static string TruncateText(string strText, int intLength)
{
    if (!(string.IsNullOrEmpty(strText)))
    {                                
        // split the text.
        var words = strText.Split(' ');

        // calculate the number of words
        // based on the provided characters length 
        // use an average of 7.6 chars per word.
        int wordLength = Convert.ToInt32(Math.Ceiling(intLength / 7.6));

        // if the text is shorter than the length,
        // display the text without changing it.
        if (words.Length <= wordLength)
            return strText.Trim();                

        // put together a shorter text
        // based on the number of words
        return string.Join(" ", words.Take(wordLength)) + " ...".Trim();
    }
        else
        {
            return "";
        }            
    }
-3
répondu V.T. 2016-05-27 13:39:11

C'est le code que j'utilise habituellement:

string getSubString(string value, int index, int length)
        {
            if (string.IsNullOrEmpty(value) || value.Length <= length)
            {
                return value;
            }
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            for (int i = index; i < length; i++)
            {
                sb.AppendLine(value[i].ToString());
            }
            return sb.ToString();
        }
-4
répondu user3390116 2017-07-13 06:04:35