anna
anna

Reputation: 1011

Set max length of a string c# but end with whole word

I want to truncate text if it is too long but i need it to truncate on a whole word. I have done the following:

 var mktText = model.Product.MarketingText;
            var countChars = mktText.Length;
            if (countChars > 180)
            {
                countChars = countChars - 180;
                mktText = mktText.Remove(180, countChars);
                mktText = mktText + "...";
            }

This code sets the max to 180 characters but will cut a word in half where i word rather have the complete word.

Any Help appreciated.

Thanks

Upvotes: 2

Views: 4781

Answers (5)

Paulo Morgado
Paulo Morgado

Reputation: 14836

Be very careful with the creation of strings.

Try something like this, instead:

public static class StringExtensions
{
    public static string Truncate(this string text, int length)
    {
        var sb = new StringBuilder(text);

        var i = Math.Min(length, sb.Length);
        if ((sb.Length > length) && !char.IsWhiteSpace(sb[i]))
        {
            while ((--i >= 0) && !char.IsWhiteSpace(sb[i]))
            {
            }
        }

        if (i > 0)
        {
            while ((--i >= 0) && char.IsWhiteSpace(sb[i]))
            {
            }
        }

        return sb.ToString(0, i + 1);
    }
}

Upvotes: 1

Kjartan
Kjartan

Reputation: 19081

This should give you what you need, with a few minor adjustments:

Edit: Adjusted to use your variables/names, and 180 for max length, etc:

var mktText = model.Product.MarketingText;
var cutPos = new string(mktText.Take(180).ToArray()).LastIndexOf(' ');
var result = new string(mktText.Take(cutPos).ToArray());

Upvotes: 0

Anton Baksheiev
Anton Baksheiev

Reputation: 2251

You need break the text at each words. and combine the new text while checking the length.

Something like this:

var listWords = [ORIGINAL_TEXT].Split(' ');
var text = string.empty;
for(var str in listWords)
{
  if((text+str).Length > 180)
     break;
  text +=str + " ";
}

I hope the idea is clear... This code needs to be modified

Upvotes: 0

Steve
Steve

Reputation: 216253

I have found an extension method, (really I don't remember where) and now it is part of my library of extensions

public static class StringExtensions
{
    public static string LimitOnWordBoundary(this string str, int count)
    {
        if (str.Length <= count - 3)
            return str;
        else
        {
            int lastspace = str.Substring(0, count - 3).LastIndexOf(' ');
            if (lastspace > 0 && lastspace > count - 20)
            {
                // limits the backward search to a max of 20 chars
                return str.Substring(0, lastspace) + "...";
            }
            else
            {
                // No space in the last 20 chars, so get all the string minus 3
                return str.Substring(0, count - 3) + "...";
            }
        }
    }
}

and now call in this way

string mktText = model.Product.MarketingText.LimitOnWordBoundary(180);

Upvotes: 1

Guffa
Guffa

Reputation: 700182

Look for the last space before that position, and cut the string there. If there is no space at all, or if it is too soon in the text, then just cut it at 180 anyway.

string mktText = model.Product.MarketingText;
if (mktText.Length > 180) {
  int pos = mktText.LastIndexOf(" ", 180);
  if (pos < 150) {
    pos = 180;
  }
  mktText = mktText.Substring(0, pos) + "...";
}

Upvotes: 5

Related Questions