Jaka metoda w klasie String zwraca tylko pierwsze N ​​znaków?

184

Chciałbym napisać metodę rozszerzenia do Stringklasy, aby jeśli ciąg wejściowy był dłuższy niż podana długość N, wyświetlane były tylko pierwsze Nznaki.

Oto jak to wygląda:

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

Jakiej String.*()metody mogę użyć, aby uzyskać tylko pierwsze Nznaki str?

Richard77
źródło

Odpowiedzi:

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
źródło
6
Czy potrzebny jest Math.Min? Myślałem, że Substring wiedział, że jeśli drugi parametr jest większy niż długość, to po prostu podłącza długość?
Martin
12
Wierzę, że to: System.String.InternalSubStringWithChecks wyrzuciłby ArgumentOutOfRange.
Paul Ruane
2
@ Martin: nie widzę, startIndex > (this.Length - length)rzuca ArgumentOutOfRangeException.
user7116
2
Chciałem zasugerować, czy Math.Min(str.Length, maxLength) == str.Lengthna wypadek, gdybyś nie utworzył niepotrzebnego ciągu, aby zwrócić „pierwsze znaki str. Długości znaków str”, ale Substring sprawdzi to za ciebie i zrobi to tylko return thiswtedy, gdy poprosisz o cały ciąg.
stevemegson,
2
Jeśli chcesz, aby metoda rozszerzenia działała na potencjalnie pustych ciągach ... zwróć ciąg? .Substring (0, Math.Min (str.Length, maxLength));
ihake
62
string truncatedToNLength = new string(s.Take(n).ToArray());  

To rozwiązanie ma niewielką zaletę, ponieważ jeśli n jest większe niż s.Length, nadal robi to dobrze.

Matt Greer
źródło
9
Tak, ale używając Linq do obcinania łańcucha? Pamiętaj tylko, że będzie to działać bardzo źle, jeśli zostanie użyte wiele razy, na przykład w pętli. Nie rób tego z przyzwyczajenia
ErikE
31

Możesz użyć LINQ str.Take(n)lub str.SubString(0, n), jeśli ten ostatni zgłosi ArgumentOutOfRangeExceptionwyjątek n > str.Length.

Pamiętać, że wersja LINQ zwraca IEnumerable<char>, więc trzeba by przekonwertować IEnumerable<char>do string: new string(s.Take(n).ToArray()).

theburningmonk
źródło
10
Nie używaj Linq do obcinania łańcuchów. To niedorzeczne.
ErikE
17

Ilekroć muszę wykonywać operacje na łańcuchach w C #, tęsknię za starym dobrym Lefti Rightfunkcjami Visual Basic, które są znacznie prostsze w użyciu niż Substring.

Dlatego w większości moich projektów w języku C # tworzę dla nich metody rozszerzeń:

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

Uwaga: część jest tam, ponieważ rzuca gdy długość ciągu wejściowego jest mniejszy niż żądanej długości, jak już wspomniano w niektórych komentarzach pod poprzednimi odpowiedziami.
Math.MinSubstringArgumentOutOfRangeException

Stosowanie:

string longString = "Long String";

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

// returns "Long String";
string left2 = longString.Left(100);
Christian Specht
źródło
Podoba mi się to, ale jeśli łańcuch byłby krótszy niż podana długość, nie dołączałby spacji. 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
strnależy sprawdzić, czy nie ma wartości null
liviriniu,
14

Po prostu:

public static String Truncate(String input,int maxLength)
{
   if(input.Length > maxLength)
      return input.Substring(0,maxLength);
   return input;
}
Majid
źródło
7
public static string TruncateLongString(this string str, int maxLength)
{
    return str.Length <= maxLength ? str : str.Remove(maxLength);
}
Kbrimington
źródło
1
Pamiętaj też, że możesz również str == null || str.Length <= maxLength
ustawić
6
Dla każdego, zastanawiając się, czy Removeczy Substringjest lepsza, nie ma różnicy. Remove(maxLength)po prostu dzwoni Substring(0,maxLength)po sprawdzeniu granic. To, co wolisz, zależy od tego, czy myślisz o obcięciu jako o „weź pierwsze znaki maxLength” czy „wyrzuć wszystko po znakach maxLength”. Oczywiście, to naprawdę oba, więc to zależy od ciebie.
stevemegson,
5

jeśli mówimy o sprawdzaniu poprawności, to dlaczego nie sprawdziliśmy, czy nie ma pozycji pustych. Jakieś konkretne powody?

Myślę, że poniżej sposób pomocy, ponieważ IsNullOrEmpty jest metodą zdefiniowaną przez system, a operatory trójskładnikowe mają cykliczną złożoność = 1, podczas gdy if () {} else {} ma wartość 2.

    public static string Truncate(string input, int truncLength)
    {
        return (!String.IsNullOrEmpty(input) && input.Length >= truncLength)
                   ? input.Substring(0, truncLength)
                   : input;
    }
sunnytyra
źródło
na czym polega problem ze złożonością cykliczną 2?
Muflix,
1

Dodałem to do mojego projektu tylko dlatego, że tam, gdzie go używam, jest duża szansa, że ​​zostanie on użyty w pętlach, w projekcie prowadzonym online, dlatego nie chciałem żadnych awarii, gdybym mógł to zarządzać. Długość pasuje do kolumny, którą mam. To jest C # 7

Tylko jedna linia:

 public static string SubStringN(this string Message, int Len = 499) => !String.IsNullOrEmpty(Message) ? (Message.Length >= Len ? Message.Substring(0, Len) : Message) : "";
Richard Griffiths
źródło
0

Metoda .NET Substring jest pełna niebezpieczeństw. Opracowałem metody rozszerzeń, które obsługują wiele różnych scenariuszy. Zaletą jest to, że zachowuje oryginalne zachowanie, ale po dodaniu dodatkowego parametru „true” następnie stosuje metodę rozszerzenia do obsługi wyjątku i zwraca najbardziej logiczne wartości, w oparciu o indeks i długość. Na przykład, jeśli długość jest ujemna i liczy się wstecz. Możesz zobaczyć wyniki testu z szeroką gamą wartości na skrzypcach pod adresem : https://dotnetfiddle.net/m1mSH9 . To da ci jasny obraz tego, jak rozwiązuje podciągi.

Zawsze dodaję te metody do wszystkich moich projektów i nigdy nie muszę się martwić o złamanie kodu, ponieważ coś się zmieniło, a indeks jest nieprawidłowy. Poniżej znajduje się kod.

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

Napisałem o tym na blogu w maju 2010 r. Pod adresem: http://jagdale.blogspot.com/2010/05/substring-extension-method-that-does.html

Vijay Jagdale
źródło
0

Częściowo ze względu na podsumowanie (z wyłączeniem rozwiązania LINQ), oto dwie jednowierszowe, które rozwiązują problem int maxLengthdopuszczenia wartości ujemnych, a także przypadku łańcucha zerowego:

  1. SubstringSposób (z odpowiedzią Paul Ruane użytkownika ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Substring(0, Math.Min(s.Length, (int)maxLength));
  1. RemoveSposób (z odpowiedzią kbrimington użytkownika ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Length > maxLength ? s.Remove((int)maxLength) : s;
liviriniu
źródło
-1
substring(int startpos, int lenght);
Tokk
źródło
-4

string.Substring (0, n); // 0 - indeks początkowy in - liczba znaków

Jagan
źródło
4
W przeciwieństwie do przyjętej odpowiedzi może to spowodować błędy indeksu poza zakresem.
Servy