Как обрезать строку .NET?

Я хотел бы обрезать строку таким образом, чтобы ее длина не превышала заданное значение. Я пишу в таблицу базы данных и хочу убедиться, что значения, которые я пишу, соответствуют ограничению типа данных столбца.

Например, было бы неплохо, если бы я мог написать следующее:

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

К сожалению, это вызывает исключение, поскольку maxLength обычно превышает границы строки value. Конечно, я мог бы написать функцию, подобную следующей, но я надеялся, что что-то подобное уже существует.

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

Где неуловимый API, который выполняет эту задачу? Есть один?

Ответ 1

К сожалению, не существует метода Truncate() в строке.. Вы должны сами написать эту логику. Однако вы можете сделать это в методе расширения, поэтому вам не нужно его дублировать повсюду:

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

Теперь мы можем написать:

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

Ответ 2

Или вместо тернарного оператора вы можете использовать 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));
    }
}

Ответ 3

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

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

    return value;
}

Это решение в основном основывается на Ray решении и открывает метод для использования в качестве метода расширения, используя это ключевое слово, как Л.Бушкин делает в своем решении.

Ответ 4

В .NET 4.0 вы можете использовать метод Take:

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

Не проверено на эффективность!

Ответ 5

Вы можете использовать LINQ... это устраняет необходимость проверки длины строки. По общему признанию, может быть, не самый эффективный, но это весело.

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

или

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

Ответ 6

Потому что тестирование производительности это весело: (используя методы расширения 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();

Метод truncate был "значительно" быстрее. #microoptimization

Рано

  • truncate10 Прошло 5788 тиков (0,5788 мс) [за 10 000 повторений, 5,788E-05 мс за]
  • smart-trunc10 истекло 8206 тактов (0,8206 мс) [в 10 000 повторений, 8,206E-05 мс за]
  • stringbuilder10 Прошло 10557 тактов (1,0557 мс) [за 10 000 повторений, 0,00010557 мс за]
  • concat10 Прошло 45495 тактов (4,5495 мс) [в 10 000 повторений, 0,00045495 мс за]
  • newstring10 72535 тактов прошло (7,2535 мс) [в 10 000 повторений, 0,00072535 мс на]

поздно

  • truncate44 Прошло 8835 тактов (0,8835 мс) [в 10 000 повторений, 8,835E-05 мс за]
  • stringbuilder44 Прошло 13106 тактов (1,3106 мс) [за 10 000 повторений, 0,00013106 мс за]
  • smart-trunc44 Прошло 14821 тактов (1,4821 мс) [в 10 000 повторений, 0,00014821 мс за]
  • newstring44 144324 тактов прошло (14,4324 мс) [за 10 000 повторений, 0,00144324 мс за]
  • concat44 Прошло 174610 тиков (17,461 мс) [за 10 тысяч повторений, 0,0017461 мс за]

Слишком долго

  • smart-trunc64 Прошло 6944 такта (0,6944 мс) [за 10 000 повторений, 6,944E-05 мс за]
  • truncate64 Прошло 7686 тиков (0,7686 мс) [за 10 000 повторений, 7,686E-05 мс за]
  • stringbuilder64 Прошло 13314 тактов (1,3314 мс) [в 10 000 повторений, 0,00013314 мс за]
  • newstring64 Прошло 177481 тактов (17,7481 мс) [за 10 000 повторений, 0,00177481 мс за]
  • concat64 Прошло 241601 тактов (24,1601 мс) [в 10 000 повторений, 0,00241601 мс за]

Ответ 7

Кажется, никто еще не опубликовал это сообщение:

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

Использование && оператор делает его немного лучше, чем принятый ответ.

Ответ 8

.NET Framework имеет API для обрезания строки следующим образом:

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

Но в приложении С# вы, вероятно, предпочтете использовать свой собственный, нежели зависимо от Microsoft.VisualBasic.dll, чья основная ценность - обратная совместимость.

Ответ 9

Я сделал в одной строке вроде этого

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

Ответ 10

Я знаю, что это старый вопрос, но вот хорошее решение:

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

Возвращает: привет...

Ответ 11

Аналогичный вариант с С# 6 Оператор Null распространения

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

Обратите внимание, что мы по существу проверяем, является ли value здесь два раза.

Ответ 12

По-прежнему нет метода Truncate в 2016 году для строк С#. Но - с помощью синтаксиса С# 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); 
  }
}

Он работает как шарм:

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

Ответ 13

Другое решение:

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

Ответ 14

Взятие @CaffGeek и его упрощение:

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

Ответ 15

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

например, строка: это тестовая строка.

Я хочу разрезать его на 11. Если мы будем использовать любой из приведенных выше методов, результат будет

это te

Это не то, что мы хотим

Метод, который я использую, также может быть не настолько совершенным, но он может справиться с большей частью ситуации.

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

Ответ 16

Почему бы и нет:

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

то есть. в случае value.Length < maxLength пробелов пробела до конца или усечения избытка.

Ответ 17

На всякий случай здесь недостаточно ответов, здесь моя:)

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

для использования:

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

Ответ 18

Для большей сложности я добавлю свою перегруженную версию, которая заменяет последние 3 символа эллипсисом в отношении параметра 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)); 
}

Ответ 19

Я предпочитаю jpierson answer, но ни один из примеров, которые я вижу, не обрабатывает недопустимый параметр maxLength, например, когда maxLength < 0.

Выбор будет либо обрабатывать ошибку в try/catch, закрепить параметр maxLength min до 0, либо maxLength меньше 0 возвращает пустую строку.

Не оптимизированный код:

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

Ответ 20

Вот решение vb.net, отметьте, что оператор if (хотя и уродливый) повышает производительность, потому что нам не нужен оператор подстроки, когда строка уже меньше, чем maxlength... Сделав его расширением до строки, он прост в использовании...

 <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

Ответ 21

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

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

Это для создания URL-адресов SharePoint, длина которых не превышает 260 символов.

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

Это может быть легко адаптировано к вашим конкретным потребностям.

Ответ 22

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

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

Ответ 23

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

Ответ 24

В дополнение к рассмотренным выше возможностям я хотел бы поделиться своим решением. Это метод расширения, который позволяет null (возвращает string.Empty), и есть второй .Truncate() для его использования с многоточием. Осторожно, это не оптимизированная производительность.

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

Ответ 25

Мои два цента с примером длины 30:

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

Ответ 26

В этом нет ничего в .net, о котором я знаю - вот моя версия, которая добавляет "...":

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

Ответ 27

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
    }

Ответ 28

Я бы рекомендовал использовать метод подстроки для той же эффективной функциональности.

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

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

Для дополнительной справки: https://www.dotnetperls.com/substring

Ответ 29

Обрезать строку

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

Ответ 30

Это код, который я обычно использую:

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