Як я можу усічити свої рядки знаком "...", якщо вони занадто довгі?


84

Сподіваюся, хтось має гарну ідею. У мене є такі рядки:

abcdefg
abcde
abc

Мені потрібно, щоб вони були вирізані таким чином, якщо вони перевищують вказану довжину:

abc ..
abc ..
abc

Чи є якийсь простий код C #, який я можу використовувати для цього?


Де ви хочете це зробити? - у додатку Форми, WPF чи на веб-сайті - будь ласка, надайте більше деталей!
Barry Kaye,

2
Проблема більшості рішень полягає в тому, що вони використовують кількість Chars як обмеження. На жаль, графічна ширина може сильно відрізнятися. А ще є сурогати UTF-16, що поєднують символи, ...
CodesInChaos

12
Це НЕ дублікат запропонованого питання. Це дуже загальне питання, тоді як пропонований дублікат - надзвичайно конкретне питання.
JasonMArcher

2
Це абсолютно не дублікат запропонованого питання.
Сет

2
Це питання навіть не близьке до запропонованої копії, видаліть атрибут дубліката. Дякую.
Даніель Лейзен

Відповіді:


146

Ось логіка, обгорнута методом розширення:

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

Використання:

var s = "abcdefg";

Console.WriteLine(s.Truncate(3));

1
Дякую Брайане. Ваша відповідь виглядає добре. Будь ласка, вибачте за моє просте запитання, але як мені використовувати метод розширення?
Мелоні,

1
@Melony: Відредаговано, щоб включити використання.
Брайан Уоттс,

11
... (еліпсис) - правильний символ для тих, хто піклується. Юнікод U + 2026.
Малако,

3
швидке доповнення для включення нульової перевірки
Джеймс

1
спасибі @Malako: value.Substring(0, maxChars) + (char)0x2026;
П'єр

8
public string TruncString(string myStr, int THRESHOLD)
{
    if (myStr.Length > THRESHOLD)
        return myStr.Substring(0, THRESHOLD) + "...";
    return myStr;
}

Ігноруйте конвенцію про іменування, це лише на той випадок, якщо йому дійсно потрібна змінна THRESHOLD або якщо вона завжди однакового розміру.

Як варіант

string res = (myStr.Length > THRESHOLD) ? myStr.Substring(0, THRESHOLD) + ".." : myStr;

Чи можна зробити це чимось одним рядком, який я міг би використовувати вбудований?
Мелоні,

2
Це може створити недійсні рядки, якщо він розділяє
кодову точку

7

Все дуже хороші відповіді, але щоб трохи прибрати це, якщо ваші рядки є реченнями, не розривайте рядок в середині слова.

private string TruncateForDisplay(this string value, int length)
{
  if (string.IsNullOrEmpty(value)) return string.Empty;
  var returnValue = value;
  if (value.Length > length)
  {
    var tmp = value.Substring(0, length) ;
    if (tmp.LastIndexOf(' ') > 0)
       returnValue = tmp.Substring(0, tmp.LastIndexOf(' ') ) + " ...";
  }                
  return returnValue;
}

Це єдина відповідь, яка не розбиває слів. Тому єдино правильний IMO.
mxmissile

@mxmissile - з огляду на дані OP, для "abcdefg", усікання на 3 символи, переходить до "abc ...", навіть якщо це спрацювало, це було б зовсім неправильно. Дані зразка OP чітко вказують на жорсткий зріз посередині суміжного тексту. Гірше, що це таке, ця відповідь призведе до помилки. Оскільки дані не містять пробілу, LastIndexOfто поверне -1, і це Substringпризведе до помилки виконання.

4

Ось версія, яка враховує довжину еліпсів:

    public static string Truncate(this string value, int maxChars)
    {
        const string ellipses = "...";
        return value.Length <= maxChars ? value : value.Substring(0, maxChars - ellipses.Length) + ellipses;
    }

4
якщо ви використовуєте символ багатоточия, то в цьому немає необхідності. Його довжина завжди буде 1const char ellipse = (char)0x2026;
П'єр,

3

У .NET Framework немає вбудованого методу, який це робить, однак це дуже простий спосіб написати самостійно. Ось кроки, спробуйте зробити це самостійно і повідомте нам, що ви придумали.

  1. Створіть метод, можливо, метод розширення public static void TruncateWithEllipsis(this string value, int maxLength)

  2. Перевірте, чи передане значення більше за maxLengthвказане за допомогою Lengthвластивості . Якщо значення valueне більше maxLength, просто поверніть value.

  3. Якщо ми не повернули передане значення як є, тоді ми знаємо, що нам потрібно скоротити. Отже, нам потрібно отримати менший відрізок рядка, використовуючи SubStringметод . Цей метод поверне менший розділ рядка на основі вказаного початкового та кінцевого значення. Кінцева позиція - це те, що було передано maxLengthпараметром, тому використовуйте це.

  4. Поверніть підрозділ рядка плюс еліпсис.

Чудовою вправою для подальшого часу буде оновлення методу і його розрив лише після повних слів. Ви також можете створити перевантаження, щоб вказати, як ви хочете показувати, що рядок був усічений. Наприклад, метод може повернути "(натисніть для отримання додаткової інформації)" замість "...", якщо ваша програма налаштована на відображення більш детальної інформації за допомогою клацання.


2

Код позаду:

string shorten(sting s)
{
    //string s = abcdefg;
    int tooLongInt = 3;

    if (s.Length > tooLongInt)
        return s.Substring(0, tooLongInt) + "..";

    return s;
}

Розмітка:

<td><%= shorten(YOUR_STRING_HERE) %></td>

Як я міг вмістити це в: "<td>" + string + "<\ td>"?
Мелоні,

2

Можливо, для цього краще застосувати метод:

string shorten(sting yourStr)
{
//Suppose you have a string yourStr, toView and a constant value 

    string toView;
    const int maxView = 3;

    if (yourStr.Length > maxView)
        toView = yourStr.Substring(0, maxView) + " ..."; // all you have is to use Substring(int, int) .net method
    else
        toView = yourStr;
return toView;
}

1
string s = "abcdefg";
if (s.length > 3)
{
    s = s.substring(0,3);
}

Ви можете використовувати функцію Substring.


1

Я знайшов це запитання після пошуку "C # truncate ellipsis". Використовуючи різні відповіді, я створив власне рішення з такими функціями:

  1. Метод розширення
  2. Додайте еліпсис
  3. Зробіть еліпсис необов’язковим
  4. Переконайтеся, що рядок не є нульовим або порожнім, перш ніж намагатися його усікати.

    public static class StringExtensions
    {
        public static string Truncate(this string value, 
            int maxLength, 
            bool addEllipsis = false)
        {
            // Check for valid string before attempting to truncate
            if (string.IsNullOrEmpty(value)) return value;
    
            // Proceed with truncating
            var result = string.Empty;
            if (value.Length > maxLength)
            {
                result = value.Substring(0, maxLength);
                if (addEllipsis) result += "...";
            }
            else
            {
                result = value;
            }
    
            return result;
        }
    }
    

Сподіваюся, це допомагає комусь іншому.



0

У мене ця проблема нещодавно. Я зберігав повідомлення "статус" у полі DB nvarcharMAX, яке містить 4000 символів. Однак мої повідомлення про стан нарощувались і вражали виняток.

Але це був не простий випадок усічення, оскільки довільне усічення осиротіло б частиною повідомлення про стан, тому мені дійсно потрібно було "скоротити" в послідовній частині рядка.

Я вирішив проблему, перетворивши рядок у масив рядків, видаливши перший елемент, а потім відновивши у рядок. Ось код ("CurrentStatus" - рядок, що містить дані) ...

        if (CurrentStatus.Length >= 3750)
        {
            // perform some truncation to free up some space.

            // Lets get the status messages into an array for processing...
            // We use the period as the delimiter, then skip the first item and re-insert into an array.

            string[] statusArray = CurrentStatus.Split(new string[] { "." }, StringSplitOptions.None)
                                    .Skip(1).ToArray();

            // Next we return the data to a string and replace any escaped returns with proper one.
            CurrentStatus = (string.Join(".", statusArray))
                                    .Replace("\\r\\n", Environment.NewLine);


        }

Сподіваюся, це допоможе комусь.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.