Improved string truncation

1

I was reviewing old codes when I found a function that "truncates" a given string after X characters: / p>

This function, unlike a substr () simple, does not leave the developer in embarrassing situations like this:

$str = 'Então, Chapeuzinho Vermelho decide tomar no cantinho, bem escondida, uma lata de leite condensado.';

var_dump( substr( $str, 45 ) . '...' );

That would result in:

  

So, Little Red Riding Hood decides to take on the ...

It's annoying ...: p

With this enhanced function, a statement like this:

var_dump( truncate( $str, 45, 'after' ) );

It would result in:

  

So Little Red Riding Hood decides to take it in the corner, ...

Much better: D

However, I found two minor issues with the third scenario covered by the function, which adds the ellipsis in the middle of the string, like this:

  

So, Little Red Riding Hood ... well hidden, a can of condensed milk.

The first of these is that, as seen in the above example, the ellipsis (or other / substring character set) is not added near the middle of the string as it should.

The second problem is only noticeable with some specific, often short, strings like this:

$str = 'Eu coloquei meu cabo de enxada no seu curral';

var_dump( truncate( $str, 35, 'center' ) );

This would produce:

  

I put my cable ... your corral

That is, the n letter of in your has been unduly suppressed.

I even managed to solve this problem by subtracting 1 (one) from strlen( $append ) of $ end .

But while this solves for small phrases, it corrupts for long phrases, causing the example of Little Red Riding Hood to result in:

  

So, Little Red Riding Hood ... ## cantinho, well hidden, a can of condensed milk.

That is, with an extra space after the string inserted (before cantinho ) in what would be the almost middle of the string (replaces with hashes to stay visible).

It's a silly problem in offset , but I could not solve it correctly.

For a time, a workaround was to replace any double spaces in the string before returning, but if possible fix instead of remedy, the better.

Any ideas?

    
asked by anonymous 18.12.2014 / 15:10

2 answers

0

Well, I took the case pro SOEn and got a fantastic answer that not only solves the problem but, at my request, it solves in a balanced way.

In other words, in addition to interpolating a configurable string between two substrings closest to the middle of the original string, it does not break the words in the middle and still causes the resulting string to have length quite close to that desired:

/**
 * Truncates a string at specified length without breaking words
 *
 * @param string $string
 *  The string to truncate
 *
 * @param integer $length
 *  The expected length after truncated
 *
 * @param string|optional $delimiter
 *  The string interpolated in the middle of string
 *
 * @return string
 *  Truncated string
 */
public static function truncate( $string, $length, $delimiter = '(...)' ) {

    if( strlen( $string ) <= $length ) return $string;

    $delimiter = sprintf( ' %s ', trim( $delimiter ) );

    $len = (int) ( ( $length - strlen( $delimiter ) ) / 2 );

    // Separate the output from wordwrap() into an array of lines

    $segments = explode( "\n", wordwrap( $string, $len ) ) ;

    /**
     * Last element's length is less than half $len, append
     * words from the second-last element
     */
    $end = end( $segments );

    /**
     * Add words from the second-last line until the end is at least
     * half as long as $length
     */
    if( strlen( $end ) <= ( $length / 2 ) && count( $segments ) > 2 ) {

        $prev = explode( ' ', prev( $segments ) );

        while( strlen( $end ) <= ( $length / 2 ) ) {
            $end = sprintf( '%s %s', array_pop( $prev ), $end );
        }
    }

    return reset( $segments ) . $delimiter . trim( $end );
}

No wonder the guy has 141k reputation: p

    
19.12.2014 / 11:28
0

One solution, but one that I do not find very efficient, but functional would be:

function trucar($texto, $qtdCaracteres) {
    $string = strip_tags($texto);
    if (strlen($texto) > $qtdCaracteres) {
        while (substr($text, $qtdCaracteres, 1) <> ' ' && ($qtdCaracteres < strlen($texto))){
            $qtdCaracteres++;
        };
    };
    return substr($texto,0,$qtdCaracteres) . '...';
}

In this case we are looking for a space after the given interval, so only cut the string when there is a space.

And the use:

$texto = "Teste de escrita de texto.";

echo trucar($texto, 15);

The result will be: Writing test ...

Source: link

    
18.12.2014 / 15:48