Cum pot trunchia un șir de caractere .NET? (Programare, C#,.Net, String, Trunchiați)

Steve Guidi a intrebat.

Aș dori să trunchez un șir de caractere astfel încât lungimea sa să nu fie mai mare decât o anumită valoare. Scriu într-un tabel de bază de date și vreau să mă asigur că valorile pe care le scriu respectă constrângerea de tip de date a coloanei.

De exemplu, ar fi bine dacă aș putea scrie următoarele:

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

Din păcate, acest lucru ridică o excepție deoarece maxLength depășește în general limitele șirului de caractere value. Desigur, aș putea să scriu o funcție de genul celei de mai jos, dar speram că există deja ceva asemănător.

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

Unde este API-ul evaziv care îndeplinește această sarcină? Există una?

Comentarii

    25

  • Pentru înregistrare, șirurile de caractere sunt imuabile, nu le poți trunchia, poți doar să returnezi o copie trunchiată a lor. Știu că e o problemă de rigoare. –  > Por John Weldon.
  • @John Weldon: Probabil că acesta este motivul pentru care funcția membră nu există – nu respectă semantica tipului de date. Pe o notă secundară, StringBuilder vă permite să trunchiați prin scurtarea lungimii, dar tot trebuie să efectuați verificarea lungimii pentru a evita lărgirea șirului. –  > Por Steve Guidi.
  • Indiferent de soluția pe care o alegeți, asigurați-vă că adăugați o verificare pentru un șir nul înainte de a apela Substring sau de a accesa proprietatea Length. –  > Por Ray.
  • @SteveGuidi – Dacă ar fi așa, atunci nu ar exista funcții precum Trim sau Replace, care se confruntă cu probleme semantice similare –  > Por Chris Rogers.
  • @JohnWeldon Mai prudenți decât sunt în mod constant cei de la Microsoft, după cum se întâmplă – sunt fericiți să documenteze, de exemplu, .Trim() într-o manieră care face să pară în mod înșelător că modifică șirul de caractere: „Îndepărtează toate caracterele de început și sfârșit de spațiu alb din obiectul String curent.” –  > Por Mark Amery.
36 răspunsuri
LBushkin

Nu există un Truncate() pe string, din păcate. Trebuie să scrieți singur acest tip de logică. Ceea ce poți face, totuși, este să înfășori acest lucru într-o metodă de extensie, astfel încât să nu trebuiască să o dublezi peste tot:

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

Acum putem scrie:

var someString = "...";
someString = someString.Truncate(2);

Comentarii

  • Soluție grozavă, dar nu uitați că aceasta funcționează doar în NET 3.5 și mai sus. Nu o încercați în NET2.0. –  > Por Maestrul Jedi Spooky.
  • Atâta timp cât sunteți în VS 2008 și, probabil, VS 2010, puteți face acest lucru chiar dacă vizați .Net 2.0. danielmoth.com/Blog/… –  > Por Mark.
  • Acest lucru va eșua atunci când maxLength este o valoare negativă. –  > Por Bernard.
  • 47

  • @Bernard, acest lucru ar trebui să eșueze dacă maxLength este negativ. Orice alt comportament ar fi neașteptat. –  > Por bojingo.
  • Puteți apela metode de extensie pe valori nule. –  > Por Joel Malone.
CaffGeek

Sau, în loc de operatorul ternar, ați putea folosi Math.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));
    }
}

Comentarii

  • Inteligent! Iar următoarea expresie este optimizată pentru a returna o referință la șirul original: value.Substring(0, value.Length). –  > Por Steve Guidi.
  • Din nefericire, nu este optimizată pentru cazurile în care value.Length este mai mică decât MaxLength, ceea ce poate fi un caz comun în unele date. De asemenea, proprietatea Length a șirului de caractere ar trebui să fie scrisă cu majuscule. –  > Por jpierson.
  • Acest lucru va eșua atunci când maxLength este o valoare negativă. –  > Por Bernard.
  • @Bernard, la fel se va întâmpla și cu multe lucruri din cadru… dar dacă verific acest lucru… fie trebuie să fie implicit maxLength la 0 fie value.Length; fie trebuie să arunc un ArgumentOutOfRangeException…ceea ce are mai mult sens în acest caz și este deja aruncat de către Substring în orice caz. –  > Por CaffGeek.
  • Un pic mai scurt: return string.IsNullOrEmpty(value) ? value : value.Substring(0, Math.Min(value.Length, maxLength)); –  > Por user1127860.
jpierson

M-am gândit să arunc în implementarea mea, deoarece cred că acoperă toate cazurile care au fost atinse de ceilalți și o face într-un mod concis, care este încă ușor de citit.

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

    return value;
}

Această soluție se bazează în principal pe soluția lui Ray și deschide metoda pentru a fi utilizată ca metodă de extensie prin utilizarea this la fel cum face LBushkin în soluția sa.

Comentarii

  • Aceasta va eșua atunci când maxLength este o valoare negativă. –  > Por Bernard.
  • 16

  • @Bernard – V-aș recomanda să nu treceți o valoare negativă pentru argumentul maxLength, deoarece este o valoare neașteptată. Metoda Substring are aceeași abordare, deci nu există niciun motiv pentru a îmbunătăți excepția pe care o aruncă. –  > Por jpierson.
  • Nu cred că verificarea IsNullOrEmpty este necesară? (1) Dacă valoarea este nulă, nu ar trebui să existe nicio modalitate de a apela această metodă de extensie asupra ei. (2) Dacă valoarea este un șir de caractere gol, verificarea value.Length > maxLength va eșua. –  > Por Jon Schneider.
  • @JonSchneider, IsNullOrEmpty este necesară deoarece aceasta este o metodă de extensie. Dacă aveți o variabilă de tip string căreia i s-a atribuit un null, compilatorul nu inserează o verificare null înainte de a apela această metodă. Din punct de vedere tehnic, aceasta este încă o metodă statică a clasei static. Deci: stringVar.Truncate(2) Se compilează ca: StringExt.Truncate(stringVar, 2); – –  > Por Jeff B.
  • Lipsa unui IsNullOrEmpty și a rezultatului NullReferenceException este o caracteristică, nu o eroare. La fel ca și str.Substring(0,10) aruncă dacă str este nul, este logic ca str.Truncate(10) să facă același lucru. –  > Por Edward Brey.
drzaus

Pentru că testarea performanței este distractivă: (folosind metodele de extensie linqpad)

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

The truncate metoda a fost „semnificativ” mai rapidă. #microoptimizare

La început

  • truncate10 5788 ticuri scurse (0.5788 ms) [în 10K repetări, 5.788E-05 ms per].
  • smart-trunc10 8206 ticuri scurse (0.8206 ms) [în 10K repetări, 8.206E-05 ms per].
  • stringbuilder10 10557 ticks scurse (1.0557 ms) [în 10K repetări, 0.00010557 ms per]
  • concat10 45495 ticks scurse (4.5495 ms) [în 10K repetări, 0.00045495 ms per]
  • newstring10 72535 ticks scurse (7,2535 ms) [în 10K repetări, 0,00072535 ms per]

Late

  • truncate44 8835 ticks scurse (0.8835 ms) [în 10K repetări, 8.835E-05 ms per]
  • stringbuilder44 13106 ticks scurse (1.3106 ms) [în 10K repetări, 0.00013106 ms per]
  • smart-trunc44 14821 ticks elapsed (1.4821 ms) [în 10K repetări, 0.00014821 ms per]
  • newstring44 144324 ticks scurse (14.4324 ms) [în 10K repetări, 0.00144324 ms per]
  • concat44 174610 ticks scurse (17.461 ms) [în 10K repetări, 0.0017461 ms per]

Prea mult timp

  • smart-trunc64 6944 ticks elapsed (0.6944 ms) [în 10K reps, 6.944E-05 ms per]
  • truncate64 7686 ticks elapsed (0.7686 ms) [în 10K reps, 7.686E-05 ms per]
  • stringbuilder64 13314 ticks scurse (1.3314 ms) [în 10K repetări, 0.00013314 ms per]
  • newstring64 177481 ticks scurse (17.7481 ms) [în 10K repetări, 0.00177481 ms per]
  • concat64 241601 ticks scurse (24.1601 ms) [în 10K repetări, 0.00241601 ms per]

Comentarii

  • Vă mulțumim pentru toate aceste repere utile! … și Linkpad este grozav! –  > Por Sunsetquest.
  • Hmm, nu sunt de acord cu acest bench. 1) Șirul de intrare val este o constantă. 2) Lungimea de trunchiere limit este constantă pentru toate cele 10k iterații. 3) Se pare că ieșirea este imediat eliminată. Toți acești factori pot determina compilatorul să optimizeze lucrurile. Mi-am făcut propriul test și am constatat că ceea ce numiți „smart-trunc” este în medie semnificativ (20%) mai rapid decât „truncate”, și asta cu 10M de iterații în modul de lansare/producție (am constatat, de asemenea, o diferență semnificativă între rularea în modul Debug și modul Release).  > Por JHBonarius.
  • @JHBonarius m-am gândit că avertismentul YMMV pentru testele de performanță ar trebui să fie oarecum evident și am vrut doar să pun mingea la bătaie 😉 și chiar dacă ai perfectă dreptate, nu uita că vorbim despre diferențe mai mici de o miime de milisecundă… –  > Por drzaus.
Dylan Nicholson

În .NET 4.0 puteți utiliza Take metoda :

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

Nu a fost testată pentru eficiență!

îmblânzește

Ați putea folosi LINQ… elimină necesitatea de a verifica lungimea șirului. Recunosc că poate nu este cel mai eficient, dar este distractiv.

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

sau

string result = new string(value.Take(maxLength).ToArray());

Comentarii

  • de ce nu este acesta răspunsul acceptat? Ce este cel mai simplu, să vă scrieți propria metodă de extensie pe care trebuie să o mențineți/documentați sau să folosiți ceva încorporat, cum ar fi .Take –  > Por Don Cheadle.
  • @mmcrae Linq ar putea fi mai direct, dar este, de asemenea, mult mai lent. Benchmark-ul meu spune ~400ms pentru Linq și doar ~24ms pentru Substring pentru 1 milion de iterații. –  > Por Hein Andre Grønnestad.
  • Această soluție nu ar trebui să fie folosită niciodată. După cum s-a spus în cele două comentarii de mai sus, există întotdeauna alocare de memorie, chiar și atunci când șirul existent nu este mai mare decât lungimea maximă. De asemenea, este foarte lentă. –  > Por Kamarey.
Marek Malczewski

O altă soluție:

return input.Substring(0, Math.Min(input.Length, maxLength));

Comentarii

  • Soluție foarte elegantă +1 –  > Por InxaneNinja.
SeanMC

Am făcut-o pe a mea într-o singură linie, cam așa

value = value.Length > 1000 ? value.Substring(0, 1000) : value;

Comentarii

  • -1; acest lucru nu adaugă absolut nimic care să nu fi fost deja în răspunsul acceptat. –  > Por Mark Amery.
  • @markamery este o alternativă mai scurtă, cu mai puțin cod de scris și de actualizat atunci când trebuie să o folosești. Nu vă place? Nu o folosiți.  > Por SeanMC.
  • Rapid, simplu și rapid. Asta este ceea ce aveam nevoie. Mulțumesc! –  > Por Peter.
Joe

.NET Framework are un API pentru a trunchia un șir de caractere ca acesta:

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

Dar într-o aplicație C# veți prefera, probabil, să vă creați propria aplicație decât să vă faceți dependență de Microsoft.VisualBasic.dll, a cărui principală rațiune de a fi este compatibilitatea cu versiunile anterioare.

Comentarii

  • „The .NET Framework are un API” vă contraziceți. Aceasta este o API VB.NET –  > Por Camilo Terevinto.
  • @CamiloTerevinto – este un API care este livrat cu .NET Framework și poate fi apelat din orice limbaj administrat. –  > Por Joe.
  • DLL-ul VB are o mulțime de lucruri bune în el. De ce sunt atât de mulți dezvoltatori c# împotriva ei? –  > Por Michael Z..
  • Din păcate, în prezent nu există suport pentru .NET Core. Într-adevăr, întregul Microsoft.VisualBasic.Strings module în .NET Core este destul de goală. –  > Por Mark Amery.
  • Deși sunt de acord cu comentariul lui Joe, totuși nu mă simt bine să numesc ceva specific pentru VB din alte limbaje. Dacă există atât de multe lucruri bune în „VB DLL”, de ce să nu le punem într-un loc comun? Cine știe ce va face Microsoft cu aceste lucruri mâine? O să oprească suportul sau ceva de genul…  > Por Kamarey.
Darren

Se pare că nimeni nu a postat asta încă:

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

Folosirea operatorului && îl face marginal mai bun decât răspunsul acceptat.

nologo

Știu că este o întrebare veche, dar iată o soluție frumoasă:

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

Returnează: hello…

Comentarii

  • @SarjanWebDev Acest caracter special apare ca „.” în cmd.exe –  > Por Neal Ehardt.
Jamie Rees

O variantă similară cu operatorul de propagare Null din C# 6

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

Vă rugăm să rețineți că, în esență, verificăm dacă value este nul de două ori aici.

Tobias Schiele

Încă nu există o metodă Truncate în 2016 pentru șirurile C#. Dar – Folosind sintaxa 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); 
  }
}

Funcționează ca un farmec:

"Truncate me".Truncate(8);
Result: "Truncate"

Sri

De ce nu:

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

adică în evenimentul value.Length < maxLength se introduc spații la sfârșit sau se trunchiază excesul.

Comentarii

  • Se generează de două ori mai multe obiecte de tip șir de caractere și s-ar putea să se arunce o excepție NullReferenceException din apelul PadRight dacă valoarea este nulă, ceea ce este inadecvat, ar trebui să fie o excepție ArgumentNullException. –  > Por Jeremy.
  • @Jeremy Nu înțeleg ” ar putea să arunce o NullReferenceException din apelul PadRight dacă valoarea este nulă”; nu am menționat „//verifică string.IsNullOrEmpty(value) și acționează în consecință.”. –  > Por Sri .
Sunsetquest

În C# 8 se poate utiliza noua caracteristică Ranges…

value = value[..Math.Min(30, value.Length)];

Edwin Beltran

Luând @CaffGeek și simplificându-l:

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

Sen K. Mathew

Kndly rețineți că trunchierea unui șir nu înseamnă pur și simplu justing tăierea unui șir doar la o lungime specificată, dar trebuie să aveți grijă să nu divizați cuvântul.

De exemplu, șirul: acesta este un șir de test.

Vreau să-l tai la 11 . Dacă folosim oricare dintre metodele prezentate mai sus, rezultatul va fi

acesta este un șir de caractere

Acesta nu este lucrul pe care îl dorim

Metoda pe care o folosesc eu poate că nu este perfectă, dar poate rezolva majoritatea situațiilor.

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

K. R.

În cazul în care nu sunt suficiente răspunsuri aici, iată-l pe al meu 🙂

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

pentru a utiliza:

"I use it like this".Truncate(5,"~")

Ognyan Dimitrov

Cei doi cenți ai mei cu o lungime de exemplu de 30 :

  var truncatedInput = string.IsNullOrEmpty(input) ? 
      string.Empty : 
      input.Substring(0, Math.Min(input.Length, 30));

Bohdan

Cea mai simplă metodă în C# recent ar fi:

string Trunc(string s, int len) => s?.Length > len ? s.Substring(0, len) : s;

Aceasta returnează valoarea trunchiată pentru șirurile mai lungi și șirul original pentru celelalte cazuri – inclusiv intrarea nulă – care este tratată de operatorul unar ?

SoftDev

De dragul (supra)complexității voi adăuga versiunea mea supraîncărcată care înlocuiește ultimele 3 caractere cu o elipsă în respect cu parametrul 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)); 
}

Ed B

Știu că există deja o tonă de răspunsuri aici, dar acesta este cel pe care l-am ales eu, care tratează atât șirurile de caractere nule, cât și situația în care lungimea transmisă este negativă:

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

deegee

Prefer răspunsul lui jpierson, dar niciunul dintre exemplele de aici pe care le pot vedea nu gestionează un parametru maxLength invalid, cum ar fi atunci când maxLength < 0.

Opțiunile ar fi fie să tratăm eroarea într-un try/catch, să fixăm parametrul maxLength min la 0, fie, dacă maxLength este mai mic de 0, să returnăm un șir gol.

Nu este un cod optimizat:

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

Comentarii

  • Rețineți că, în implementarea mea, am ales să nu gestionez cazul în care lungimea maximă este mai mică de 0, deoarece m-am gândit că singurul lucru pe care l-aș putea face ar fi să arunc un ArgumentOutOfOfRangeExcpetion, ceea ce, în esență, face string.Substring() pentru mine. –  > Por jpierson.
Jeroen Bom

Iată o soluție vb.net, rețineți că instrucțiunea if (deși urâtă) îmbunătățește performanța deoarece nu avem nevoie de instrucțiunea substring atunci când șirul este deja mai mic decât maxlength…Făcând-o o extensie a șirului, este ușor de utilizat…

 <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

Comentarii

  • În VB.net puteți înlocui „Not String.IsNullOrEmpty(String__1)” cu „String__1 <> Nothing”. Este un pic mai scurt. Valoarea implicită pentru șiruri de caractere este un șir gol. Folosind „<> Nothing” se verifică atât cazul null, cât și cel al șirului gol. Testați-o cu: Truncate(„”, 50) și Truncate(Nothing, 50) –  > Por jrjensen.
  • În VB puteți face Left(string, maxlength) –  > Por Michael Z..
Paul Haan

Știu că există deja o tonă de răspunsuri, dar nevoia mea era să păstrez intact începutul și sfârșitul șirului, dar să-l scurtez sub lungimea maximă.

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

Acest lucru este pentru crearea de URL-uri SharePoint care au o lungime maximă de 260 de caractere.

Nu am făcut din lungime un parametru, deoarece este o constantă 260. De asemenea, nu am făcut din lungimea primului subșir un parametru, deoarece vreau ca acesta să se întrerupă într-un anumit punct. În cele din urmă, al doilea subșir este lungimea sursei – 20, deoarece cunosc structura dosarului.

Acest lucru ar putea fi ușor adaptat la nevoile dvs. specifice.

Edward Brey

Biblioteca populară Humanizer are o Trunchiat metoda Pentru a o instala cu NuGet:

Install-Package Humanizer

Ray

Nu există nimic în .net pentru acest lucru, din câte știu eu – iată versiunea mea care adaugă „…”:

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

Comentarii

  • Versiunea dvs. va oferi șiruri de caractere care sunt cu 3 caractere mai lungi decât lungimea solicitată, în cazul în care sunt trunchiate. În plus, punctele triple sunt de fapt doar semnificative în reprezentare, nu le-aș stoca într-o bază de date ca aceasta, care este cazul de utilizare pe care l-a dat OP. –  > Por MarioDS.
Sud

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

Comentarii

  • De ce precedeți numele metodei publice cu o subliniere? –  > Por Michael Z..
Raymond Osterbrink

Ca o completare la posibilitățile discutate mai sus, aș dori să vă împărtășesc soluția mea.Este o metodă de extensie care permite null (returnează string.Empty), de asemenea, există un al doilea .Truncate() pentru a o utiliza cu o elipsă. Atenție, nu este optimizată din punct de vedere al performanței.

public static string Truncate(this string value, int maxLength) =>
    (value ?? string.Empty).Substring(0, (value?.Length ?? 0) <= (maxLength < 0 ? 0 : maxLength) ? (value?.Length ?? 0) : (maxLength < 0 ? 0 : maxLength));
public static string Truncate(this string value, int maxLength, string ellipsis) =>
    string.Concat(value.Truncate(maxLength - (((value?.Length ?? 0) > maxLength ? ellipsis : null)?.Length ?? 0)), ((value?.Length ?? 0) > maxLength ? ellipsis : null)).Truncate(maxLength);

Edward Brey

Puteți crea o metodă Truncate metodă de extensie care compară lungimea maximă în raport cu lungimea șirului de caractere și apelează la Substring dacă este necesar.

Dacă doriți un comportament de tratare a valorilor nule care să fie similar cu cel al metodei Substring, nu includeți o verificare a caracterului nul. În acest fel, la fel ca str.Substring(0, 10) aruncă un NullReferenceException dacă str este nul, la fel va face și str.Truncate(10).

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

Nae

Pe baza acestui lucru și a acestui lucru, iată două versiuni care vor funcționa și pentru valorile negative ale valorilor „până la”. Aceasta dintâi nu permite valori negative în mod silențios prin plafonarea la 0:

public static string Truncate(this string value, int maxLength)
{
    return string.IsNullOrEmpty(value) ?
        value :
        value.Substring(0, Math.Max(0, Math.Min(value.Length, maxLength)));
}

Aceasta merge în cerc:

private static int Mod(this int a, int n) => (((a %= n) < 0) ? n : 0) + a;

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

chillitom

Iată o C# 9 de o linie:

public static string Truncate(this string value, int maxLength) => value is null or "" || value.Length <= maxLength ? value : value[..maxLength];

TapiocaCom
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
    }

Comentarii

  • The ToArray() aici este doar un efort inutil; folosind, de ex. String.Concat puteți construi un șir de caractere dintr-o enumerare de caractere fără a fi nevoie să treceți printr-un array. –  > Por Mark Amery.
V.T.

Trunchiați șirul de caractere

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

Comentarii

  • Acest lucru nu răspunde la întrebarea lui OP. În primul rând, ar trebui să fie o funcție membră (deși ați scris-o ca o metodă de extensie). În al doilea rând, OP nu specifică faptul că textul trebuie să fie divizat, iar cuvintele trebuie să fie trunchiate la aproximativ 7,6 caractere pe cuvânt. –  > Por Wicher Visser.
  • 7,6 este doar un număr. puteți scrie orice alt număr doriți. S-a întâmplat ca aceasta să fie o lungime medie a cuvintelor în limba engleză. Am găsit-o pe Google. Utilizarea divizării este doar o modalitate ușoară de a împărți cuvintele în funcție de spațiu. Nu cred că doriți să afișați o jumătate de cuvânt! Deci, dacă nu faceți o buclă pentru a găsi spațiile goale, ceea ce va necesita mai mult cod, aceasta este o modalitate ușoară de a trunchia un șir și de a afișa cuvinte întregi. Acest lucru vă va asigura că un șir nu este mai lung decât lungimea dată și nu veți avea cuvinte întrerupte. –  > Por V.T..
utilizator3390116

Acesta este codul pe care îl folosesc de obicei:

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

Comentarii

  • Rețineți că concatenarea șirurilor de caractere cu += este o operațiune costisitoare, mai ales atunci când se reconstruiește caracter cu caracter. Șirurile .NET sunt imuabile, ceea ce înseamnă că, în acest caz, un nou șir este creat de fiecare dată în bucla dvs. –  > Por Steve Guidi.
  • @SteveGuidi șirurile de caractere nu sunt imuabile, ele doar se prefac că sunt imuabile. Mi-aș dori ca șirurile să fie adevărate primitive imuabile, astfel încât să pot avea șiruri și șiruri?, dar din păcate nu sunt primitive. –  > Por Chris Marisic.
  • Spuneți scump ca și cum costul de performanță ar fi semnificativ, am schimbat-o pentru a folosi stringBuilder, dar mi se pare că cu += este mai ușor de văzut ce se întâmplă, am vrut doar ca OP să înțeleagă cu ușurință codul. –  > Por utilizator3390116.
SethGoodluck

Aș recomanda utilizarea metodei substring pentru aceeași funcționalitate eficientă.

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

Aceasta are avantajul de a vă permite să îmbinați șirul din ambele părți sau chiar undeva la mijloc fără a scrie metode suplimentare. Sper că vă ajută 🙂

Pentru referință suplimentară: https://www.dotnetperls.com/substring

Comentarii

  • Dacă șirul dvs. este mai mic decât n, va eșua. Scopul trunchierii este de a preveni acest lucru. –  > Por JSON.