it-swarm.com.ru

Как обрезать строку .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, который выполняет эту задачу? Есть один?

340
Steve Guidi

К сожалению, в строке нет метода 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);
521
LBushkin

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

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

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

    return value;
}

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

35
jpierson

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

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

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

29
Dylan Nicholson

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

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

или же

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

Потому что тестирование производительности - это весело: (используя методы расширения 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 мс) [в 10K повторений, 0.00177481 мс за] 
  • concat64 Прошло 241601 тактов (24,1601 мс) [в 10 000 повторений, 0,00241601 мс за] 
20
drzaus

.NET Framework имеет API для усечения строки, подобной этой:

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

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

11
Joe

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

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

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

10
Darren

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

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

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

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

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

5
Jamie Rees

Взяв @CaffGeek и упростив его:

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

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

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

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

это тэ

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

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

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());
} 
4
Sen K. Mathew

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

Отлично работает:

"Truncate me".Truncate(8);
Result: "Truncate"
4
Tobias Schiele

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

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

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

4
nologo

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

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

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

3
Sri

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

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,"~")
3
K. R.

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

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

Ради (чрезмерной) сложности я добавлю свою перегруженную версию, которая заменяет последние 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)); 
}
2
SoftDev

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

    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. Я также не сделал первую длину подстроки параметром, потому что я хочу, чтобы она ломалась в определенной точке. Наконец, вторая подстрока - это длина источника - 20, поскольку я знаю структуру папок. 

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

1
Paul Haan

Я предпочитаю ответ jpierson, но ни один из приведенных здесь примеров не обрабатывает недопустимый параметр 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;
}
1
deegee

Вот решение vb.net, отметьте, что оператор if (хотя и уродливый) повышает производительность, потому что нам не нужен оператор substring, когда строка уже меньше 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
1
Jeroen Bom

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

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);
}
1
Ed B

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

В качестве дополнения к рассмотренным выше возможностям я хотел бы поделиться своим решением .. Это метод расширения, который позволяет 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);
0
Raymond Osterbrink