String sınıfındaki hangi yöntem yalnızca ilk N karakteri döndürür?


185

StringGiriş dizesi sağlanan uzunluktan daha uzunsa N, yalnızca ilk Nkarakterlerin görüntülenmesi için sınıfa bir uzantı yöntemi yazmak istiyorum .

Şöyle görünüyor:

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

String.*()Yalnızca ilk Nkarakterlerini almak için hangi yöntemi kullanabilirim str?

Yanıtlar:


375
public static string TruncateLongString(this string str, int maxLength)
{
    if (string.IsNullOrEmpty(str))
        return str;
    return str.Substring(0, Math.Min(str.Length, maxLength));
}

6
Math.Min gerekli mi? Substring'in ikinci parametrenin uzunluktan daha büyük olması durumunda, uzunluğa takılı olduğunu bildiğini düşündüm.
Martin

12
Ben olduğuna inanıyorum: System.String.InternalSubStringWithChecks ArgumentOutOfRange atmak.
Paul Ruane

2
@Martin: Görebildiğimden değil, startIndex > (this.Length - length)atar ArgumentOutOfRangeException.
user7116

2
Eğer Math.Min(str.Length, maxLength) == str.Length"str ilk str.Length karakterleri" dönmek için gereksiz bir dize oluşturma durumunda sonunda kontrol önerecektim , ama Substring sizin için yapar ve sadece return thistüm dize sorduysanız yapar .
stevemegson

2
Uzantı yönteminin potansiyel olarak boş dizelerde çalışmasını istiyorsanız ... return str? .Substring (0, Math.Min (str.Length, maxLength));
ihake

62
string truncatedToNLength = new string(s.Take(n).ToArray());  

Bu çözümün küçük bir bonusu vardır, çünkü n, s.Length'dan büyükse, hala doğru olanı yapar.


9
Evet, ama bir dizeyi kısaltmak için Linq mi kullanıyorsun? Bir döngü gibi birçok kez kullanıldığında bunun çok kötü performans göstereceğini unutmayın. Bunu alışkanlık meselesi olarak yapma
ErikE

31

LINQ str.Take(n)veya str.SubString(0, n)ikincisinin bir ArgumentOutOfRangeExceptionistisna atacağı yerde kullanabilirsiniz n > str.Length.

LINQ sürümünün a döndürdüğünü unutmayın IEnumerable<char>, bu nedenle IEnumerable<char>to string: öğesini dönüştürmeniz gerekir new string(s.Take(n).ToArray()).


10
Dizeleri kısaltmak için Linq kullanmayın. Saçma.
ErikE

18

Ben C # dize manipülasyonlar yapmak zorunda zaman, ben iyi eski özlüyorum Leftve Rightdaha kullanmak daha basittir Visual Basic, işlevleri Substring.

C # projelerimin çoğunda, onlar için uzantı yöntemleri oluşturuyorum:

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

Not: çünkü parçası olduğunu bir atar zaten önceki cevaplar altında bazı yorumlarda belirtildiği gibi girdi dize ait uzunluk, istenen uzunluğundan daha küçük olduğunda.
Math.MinSubstringArgumentOutOfRangeException

Kullanımı:

string longString = "Long String";

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

// returns "Long String";
string left2 = longString.Left(100);

Bunu beğendim, ancak dize verilen uzunluktan daha kısa olsaydı boşluk eklemezdi. 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

strnull için kontrol edilmesi gerekiyor
liviriniu

14

basitçe:

public static String Truncate(String input,int maxLength)
{
   if(input.Length > maxLength)
      return input.Substring(0,maxLength);
   return input;
}

7
public static string TruncateLongString(this string str, int maxLength)
{
    return str.Length <= maxLength ? str : str.Remove(maxLength);
}

1
Ayrıca, koşulustr == null || str.Length <= maxLength
kbrimington

6
Olup olmadığını merak herkes için Removeveya Substringdaha iyi, hiçbir fark yoktur. Remove(maxLength)sadece Substring(0,maxLength)biraz sınır kontrol ettikten sonra arar . Tercih ettiğiniz, kesmeyi "ilk maxLength karakterleri al" veya "maxLength karakterlerden sonra her şeyi atmak" olarak düşünüp düşünmemenize bağlıdır. Tabii ki, gerçekten ikisi de bu yüzden size bağlı.
stevemegson

5

doğrulamalardan bahsediyorsak, neden boş dize girişlerini kontrol etmedik de. Belirli bir nedeni var mı?

IsNullOrEmpty sistem tanımlı bir yöntem olduğundan ve üçlü işleçlerin siklomatik karmaşıklık = 1, eğer () {} else {} değeri 2 ise aşağıdaki şekilde yardımcı düşünüyorum.

    public static string Truncate(string input, int truncLength)
    {
        return (!String.IsNullOrEmpty(input) && input.Length >= truncLength)
                   ? input.Substring(0, truncLength)
                   : input;
    }

siklomatik karmaşıklık 2 ile ilgili sorun nedir?
Muflix

1

Bunu projeme ekledim çünkü kullandığım yerde döngülerde kullanılma şansı yüksek, çevrimiçi olarak barındırılan bir projede bu yüzden yönetebilseydim herhangi bir çökme istemedim. Uzunluk sahip olduğum bir sütuna uyuyor. C # 7

Sadece bir satır:

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

0

.NET Substring yöntemi tehlikeyle doludur. Çok çeşitli senaryoları ele alan uzatma yöntemleri geliştirdim. Güzel bir şey, orijinal davranışı korur, ancak ek bir "true" parametresi eklediğinizde, istisnayı işlemek için uzantı yöntemine başvurur ve dizin ve uzunluğa bağlı olarak en mantıklı değerleri döndürür. Örneğin, uzunluk negatifse ve geriye doğru sayarsa. Test sonuçlarına çok çeşitli değerlerle bakabilirsiniz: https://dotnetfiddle.net/m1mSH9 . Bu size alt dizeleri nasıl çözdüğü konusunda net bir fikir verecektir.

Bu yöntemleri her zaman tüm projelerime ekliyorum ve asla kod kırma konusunda endişelenmem gerekiyor, çünkü bir şey değişti ve dizin geçersiz. Kod aşağıdadır.

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

Mayıs 2010'da bu konuda blog yazdım: http://jagdale.blogspot.com/2010/05/substring-extension-method-that-does.html


0

Kısaca özetleme amacıyla (LINQ çözümü hariç), int maxLengthnegatif değerlere izin verme uyarısını ve ayrıca boş dize durumunu ele alan iki tek astar :

  1. SubstringYolu (dan Paul Ruane cevabı ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Substring(0, Math.Min(s.Length, (int)maxLength));
  1. Remove(Dan yönlü kbrimington cevabı ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Length > maxLength ? s.Remove((int)maxLength) : s;


-4

(0, N) String.substring; // 0 - başlangıç ​​dizini ve n - karakter sayısı


4
Kabul edilen cevabın aksine, bu sınır dışı hataların indeksine yol açabilir.
Servy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.