PDA

View Full Version : Shorten a string?



alexjewell
12-03-2007, 09:57 PM
Hey, there's a string I'm taking from a database and displaying. I would like to shorten that string if it is longer than a certain number of characters and add "..." at the end. How would I do this? Thanks.

thetestingsite
12-03-2007, 10:00 PM
Check out the following thread:
http://www.dynamicdrive.com/forums/showthread.php?t=18065&highlight=substr

Hope this helps.

Twey
12-03-2007, 10:10 PM
Better would be a soft limit in words, then a hard limit in characters:
function truncate_passage($tr, $wordlimit = 20, $charlimit = 0, $tail = '...') {
$utail = false;

if($wordlimit) {
$tr = explode(' ', $tr);
$utail = count($tr) > $wordlimit;
$tr = implode(' ', array_slice($tr, 0, $wordlimit));
}

if($charlimit) {
$utail = $utail || strlen($tr) > $charlimit;
$tr = substr($tr, 0, $charlimit);
}

if($utail) $tr .= $tail;

return $tr;
}

alexjewell
12-03-2007, 10:17 PM
I think I may have a use for both. Thanks guys :)

boogyman
12-04-2007, 01:57 PM
only question I have is what is "utail" ?

BEGIN


I think I may have a use for both. Thanks guys :)

that script allows both. truncate_passage($tr, $wordlimit = 20, $charlimit = 0, $tail = '...')

END

Twey
12-04-2007, 02:46 PM
alexjewell, there's nothing that does that mine doesn't.

boogyman, whether to append the tail or not. I called it $tail, then made it into a function, and $tail was the logical name for the fourth parameter, so I had to rename it.

alexjewell
12-04-2007, 03:35 PM
I used substr and strlen:



if(strlen($row['Title'])){ $row['Title'] = substr($row['Title'],0,25).'...';}

boogyman
12-04-2007, 03:48 PM
I used substr and strlen:



if(strlen($row['Title'])){ $row['Title'] = substr($row['Title'],0,25).'...';}


that will be fine if this is the one and only time you will EVER need to do this, including not only in this script but forever, which the liklihood of you encountering something else you would like to limit is very very slim.

Twey was giving you a generic fuction that you could re-use over and over and over. and cover a number of parameters and options.

but we aren't here to dictate how you write your site, so I'm happy you found the solution. a good reference is www.php.net which is the homesite of the programming language, and it is very well documented.


Twey, I thought it was just a check to see whether or not to include the tail but what shook me was


$utail = count($tr) > $wordlimit;



$utail = $utail || strlen($tr) > $charlimit;


That first one is the one that threw me off because its setting the tail by default where the second is creating a check first?

Twey
12-04-2007, 04:43 PM
I used substr and strlen:The main problem with this is that it's liable to cut off the string halfway through a word: "I welcome you all here tod" while mine will try not to do so where possible: "I welcome you all here today..." That was the main problem I was trying to solve. The hard character limit is off by default but should probably be set too, since otherwise one very long word wouldn't get truncated.
That first one is the one that threw me off because its setting the tail by default where the second is creating a check first?What? The former is equivalent to:
if(count($tr) > $wordlimit) // if there are more words than allowed
$utail = true;And the latter:
if($utail || strlen($tr) > $charlimit)
$utail = true;Without the check for $utail, the function wouldn't append the dots if the string were truncated by words and then was shorter than the character limit.

djr33
12-04-2007, 10:28 PM
Another thought--

function cut_it($str,$len=20) { //default is 20, but you can switch to anything you want here on when calling it
if (strlen($str)<=$len) { return $str; }
$str = wordwrap($str,$len); //defaults to the behaviour twey setup
$str = explode("\n",$str,2); //lazy-- you could use substr/strpos, etc
return $str[0];
}
$test = 'whatever and stuff this is some text etc';
$test = cut_it($test,15);

Twey
12-05-2007, 07:15 AM
Works, but one long word (or just a random string of characters, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...) would bypass it.

djr33
12-05-2007, 07:44 AM
//shrug


function cut_it($str,$len=20) { //default is 20, but you can switch to anything you want here on when calling it
if (strlen($str)<=$len) { return $str; }
$str = wordwrap($str,$len); //defaults to the behaviour twey setup
$str = explode("\n",$str,2); //lazy-- you could use substr/strpos, etc
$str = $str[0];
if ($str>$len) {
$str = substr($str,0,$len-3).'...';
}
return $str;
}
$test = 'whatever and stuff this is some text etc';
$test = cut_it($test,15);

Anyway, your function probably makes more sense. If anyone wants to use this, you could (or I would) make the ending '...' dynamic.

Twey
12-05-2007, 07:52 AM
Mm. Handy though. Here:
function truncate_string($tr, $len, $tail = '...') {
if(strlen($tr) > $len) {
$tr = explode("\n", wordwrap(str_replace("\n", "\0", $tr), $len), 2);
$tr = str_replace("\0", "\n", substr($tr[0], 0, $len) . $tail);
}
return $tr;
}

djr33
12-05-2007, 01:55 PM
function truncate_string($tr, $len, $tail = '...') {
if(strlen($tr) > $len) {
$len = $len-3;
$tr = explode("\n", wordwrap(str_replace("\n", "\0", $tr), $len), 2);
$tr = str_replace("\0", "\n", substr($tr[0], 0, $len) . $tail);
}
return $tr;
}

Twey
12-05-2007, 03:20 PM
No. For a start I just don't think that's a good idea: the actual string will be truncated shorter than the specified number of characters. If I say I want 20 characters of the string to be displayed, I'd be mightily annoyed if it actually got cut down to 17, and that would take me a while to debug if this function was closed off in a black box somewhere. It's just not intuitive.

Secondly, if it were to be done, you'd need strlen($tail) not a static 3, you'd have to take into account what to do if the tail were longer than $len, &c., none of which options are at all intuitive in my opinion.

Thirdly, what's wrong with $len -= 3;?

djr33
12-05-2007, 06:39 PM
-=3 is fine.

Well, I can see what you mean about it being ambiguous, but having the string longer than the allowed maximum is strange. You have only 20 characters of space, but then need room for the elipses?

And, yes, you're right-- strlen($tail).

Twey
12-05-2007, 10:23 PM
You have only 20 characters of space, but then need room for the elipses?I might set it to 20 then be a little puzzled when it didn't quite fit, but I'd work it out pretty quickly. If I set it to 20 and only got 17 characters, however, I wouldn't immediately recognise the source of the bug.

djr33
12-05-2007, 10:30 PM
If I set it to 20 and only got 17 characters

No... it WOULD Be 20 characters. Do dots not count? You are outputting a string to fit in a small space. (Let's assume this is courier, or another such font, so we don't need to consider [as it would be very difficult anyway, though perhaps a fun task for GD] the width of individual characters].)

You have 20 spots-- you get 20 characters. Good. You get 23... and... problem.

Though it's only 17 of CONTENT, that still is how much space you have. To maximize content, use no tail.


As for having a tail longer than the character limit... uh... that defeats the point. It's like asking "How many pickup trucks can I fix under my table?"-- and hopefully no one would do that.

Twey
12-05-2007, 10:33 PM
No... it WOULD Be 20 characters. Do dots not count?Twenty characters of the string.
As for having a tail longer than the character limit... uh... that defeats the point. It's like asking "How many pickup trucks can I fix under my table?"-- and hopefully no one would do that.That's true, but in a real case you'd have to deal with it somehow.

djr33
12-05-2007, 10:47 PM
Twenty characters of the string.No. The idea isn't twenty characters of the string, or twenty you like, or twenty you want-- it's twenty that fits within a certain area. If you JUST want the string, go ahead and remove the ellipses... guess that serves no point. So, use no tail, and then you get up to exactly 20 characters.


That's true, but in a real case you'd have to deal with it somehow.In a real case where someone wants to place pickup trucks under a table? There might be someone (probably drunk) who would try such a thing. But it doesn't mean anyone really wants to. If you really want to add a longer string to the end, it's a different situation entirely.

You could set the function to return an array, the second parameter of which is if the string needs the tail or not (which, if it's longer, would probably actually not need it), then check that and add it manually after in such a situation.

I can't think of a situation where I'd want to have it return the number + tail*, nor one in which I'd want a bizarre tail.

(*Actually, just setting the initial functionc all for thisfunc($str,$len+strlen($tail),$tail) would give a reasonable response because you'd get up to 3 characters, then, once it was 3 less than the max length, it would add on the tail. Guess it would work.)


Anyway, there are theoretical needs for making this function handle anything, but there's a reason that the space shuttle doesn't have a propeller and torpedoes.

Twey
12-06-2007, 12:01 AM
Heh :) A function should, however, handle out-of-bounds inputs as gracefully as possible. It's a basic principle of programming.

I still think cutting the string more than the user explicitly requested is ugly and unintuitive to the user.

djr33
12-06-2007, 02:10 AM
It's about fitting it somewhere, not cutting the string. Name it fit2len($str,$len,$tail), and maybe that makes more sense. We may be seeing it as solving different problems.

Out-of-bounds inputs are usually dealt with by errors. Add an error if you'd like.

Twey
12-06-2007, 10:24 AM
It does make more sense like that, but as you say, that's a different problem.

djr33
12-06-2007, 07:04 PM
We may be seeing it as solving different problems.
I didn't say I was solving a different problem, but that we were. Alex wants to display a preview in a limited region, meaning that he would want it to not overfill the space (probably thereby stretching his layout).