Reputation: 1011
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
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
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
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
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
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