Какой метод в классе String возвращает только первые N символов?

184

Я хотел бы написать метод расширения для Stringкласса, чтобы, если входная строка длиннее указанной длины N, Nотображались только первые символы.

Вот как это выглядит:

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

Какой String.*()метод я могу использовать, чтобы получить только первые Nсимволы str?

Richard77
источник

Ответы:

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));
}
Пол Руане
источник
6
Нужен ли Math.Min? Я думал, что Substring знает, что если второй параметр больше длины, он просто включается в длину?
Мартин
12
Я считаю, что это: System.String.InternalSubStringWithChecks будет бросать ArgumentOutOfRange.
Пол Руане
2
@Martin: не то, что я вижу, startIndex > (this.Length - length)бросает ArgumentOutOfRangeException.
user7116
2
Я собирался предложить проверить, если Math.Min(str.Length, maxLength) == str.Lengthв итоге вы создаете ненужную строку для возврата «первых символов str.Length строки str», но Substring выполняет эту проверку для вас и просто делает, return thisесли вы запросили всю строку.
Stevemegson
2
Если вы хотите, чтобы метод расширения работал с потенциально нулевыми строками ... return str? .Substring (0, Math.Min (str.Length, maxLength));
ihake
62
string truncatedToNLength = new string(s.Take(n).ToArray());  

Это решение имеет крошечный бонус в том, что если n больше s.Length, оно по-прежнему работает правильно.

Мэтт Грир
источник
9
Да, но используя Linq для обрезания строки? Просто знайте, что это будет работать очень плохо, если используется много раз, например, в цикле. Не делайте это по привычке
ErikE
31

Вы можете использовать LINQ str.Take(n)или str.SubString(0, n), где последний будет генерировать ArgumentOutOfRangeExceptionисключение для n > str.Length.

Ум , что версия LINQ возвращает IEnumerable<char>, поэтому вам придется конвертировать IEnumerable<char>в string: new string(s.Take(n).ToArray()).

theburningmonk
источник
10
Не используйте Linq для обрезания строк. Это вздор.
ErikE
17

Всякий раз , когда я должен делать со строками в C #, я скучаю старый добрый Leftи Rightфункции из Visual Basic, которые намного проще в использовании , чем Substring.

Поэтому в большинстве моих проектов на C # я создаю методы расширения для них:

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

Примечание
. Math.MinЧасть существует потому, что Substringвыбрасывает, ArgumentOutOfRangeExceptionкогда длина входной строки меньше запрашиваемой длины, как уже упоминалось в некоторых комментариях к предыдущим ответам.

Использование:

string longString = "Long String";

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

// returns "Long String";
string left2 = longString.Left(100);
Кристиан Шпехт
источник
Мне это нравится, но если строка была короче заданной длины, она не добавляла бы пробелы. 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
strнужно проверить на нуль
liviriniu
14

Просто:

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);
}
kbrimington
источник
1
Также обратите внимание, что вы могли бы также сделать метод расширения нулевым, изменив условие наstr == null || str.Length <= maxLength
kbrimington
6
Для тех, кто интересуется, лучше Removeили Substringнет, нет никакой разницы. Remove(maxLength)просто звонит Substring(0,maxLength)после небольшой проверки границ. То, что вы предпочитаете, зависит от того, считаете ли вы усечение «взять первые символы maxLength» или «выбросить все после символов maxLength». Конечно, это действительно так, так что решать вам.
Stevemegson
5

если мы говорим о проверках также, почему мы не проверили на пустые строковые записи. Какие-то конкретные причины?

Ниже приведена справка, поскольку IsNullOrEmpty является системным методом, а троичные операторы имеют цикломатическую сложность = 1, тогда как if () {} else {} имеет значение 2.

    public static string Truncate(string input, int truncLength)
    {
        return (!String.IsNullOrEmpty(input) && input.Length >= truncLength)
                   ? input.Substring(0, truncLength)
                   : input;
    }
sunnytyra
источник
В чем проблема цикломатической сложности 2?
Muflix
1

Я добавил это в свой проект только потому, что там, где я его использую, высока вероятность того, что он будет использован в циклах, в проекте, размещенном в Интернете, поэтому я не хотел никаких сбоев, если бы мог управлять им. Длина соответствует столбцу, который у меня есть. Это C # 7

Всего одна строка:

 public static string SubStringN(this string Message, int Len = 499) => !String.IsNullOrEmpty(Message) ? (Message.Length >= Len ? Message.Substring(0, Len) : Message) : "";
Ричард Гриффитс
источник
0

Метод .NET Substring таит в себе опасность. Я разработал методы расширения, которые обрабатывают широкий спектр сценариев. Приятно, что он сохраняет исходное поведение, но когда вы добавляете дополнительный «истинный» параметр, он затем обращается к методу расширения для обработки исключения и возвращает большинство логических значений, основанных на индексе и длине. Например, если длина отрицательна и считается в обратном направлении. Вы можете посмотреть результаты теста с различными значениями на скрипке по адресу: https://dotnetfiddle.net/m1mSH9 . Это даст вам четкое представление о том, как он разрешает подстроки.

Я всегда добавляю эти методы ко всем своим проектам, и мне никогда не нужно беспокоиться о взломе кода, потому что что-то изменилось и индекс недействителен. Ниже приведен код.

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

Я писал об этом в мае 2010 года по адресу: http://jagdale.blogspot.com/2010/05/substring-extension-method-that-does.html

Виджей Джагдейл
источник
0

Частично ради суммирования (исключая решение LINQ), вот два однострочника, которые обращаются к int maxLengthпредостережению о разрешении отрицательных значений, а также к случаю пустой строки:

  1. SubstringПуть (от ответа Павла Ruane в ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Substring(0, Math.Min(s.Length, (int)maxLength));
  1. RemoveПуть (от ответа kbrimington в ):
public static string Truncate(this string s, uint maxLength) =>
    s?.Length > maxLength ? s.Remove((int)maxLength) : s;
liviriniu
источник
-4

String.substring (0, п); // 0 - начальный индекс и n - количество символов

Джагана
источник
4
В отличие от принятого ответа, это может привести к ошибкам индексации за границами.
Servy