2014-12-18 3 views
3

긴 문자열을 특정 수의 문자로 자르고 중간에 다른 사용자 정의 문자열을 보간하려고 시도하고 있습니다. 문자열이 잘 렸습니다. 그리고 동시에, 나는 반쪽으로 부서지지 않는 말을하려고 노력하고 있습니다. 예 : 빠른 갈색 여우가 (함수 매개 변수로) 게으른 개 정의도트로 단어를 끊지 않고 긴 문자열을 자르십시오.

하면 뛰어 넘었다

는 결과 문자열이 있어야 할 20 자 문자열을자를 뭔가 같은 :

빠른에게 갈색 ... 게으른 개

가장 가까운 구현 왔어요했다 :

function truncate($string, $length, $append = NULL) { 

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

    $append = (strlen($append) ? sprintf(' %s ', $append) : ' ... '); 

    $start = round($length/2); 
    $start = strlen(substr($string, 0, (strpos(substr($string, $start), ' ') + $start))); 

    $end = ($start - strlen($append)); 
    $end = strlen(substr($string, 0, strrpos(substr($string, $start + strlen($append) - 1), ' '))); 

    return substr($string, 0, $start) . $append . substr($string, (strlen($string) - $end)); 
} 

그러나 길이가 다른 문자열에서는 부드럽게 실행되지 않을뿐만 아니라 정의 된 크기로 잘리지 않습니다. 나는 (때문에의 sprintf() 이상 $가를 추가로 사용하는 공백에 대한 잘못된 수학의) 공백 문자를 중복 수신하고있어 일부 문자열의

는 때때로 하나 개의 문자는 보간 문자열로 단어 가까운에서 제거하고 때때로 단어가 반대로 깨져서는 안됩니다. 에서

truncate($str, 20); 

결과 :

위의 문자열, 예를 들어,이처럼 사용할

빠른 갈색 ... 게으른 개 이상 PED는

+0

길이 20은 어디에 적합합니까? 샘플 문자열 출력은 실제로 32이므로 20시에 "빠른 ... 게으른 개"가 될 것입니까? –

답변

2

방지하려면 중간 단어 자르기, 나는 기본적으로 이미 그 능력을 가지고 있기 때문에 먼저 wordwrap()을 찾습니다.

그래서 내가 취해야 할 접근법은 wordwrap()을 사용하여 원하는 총 길이의 절반에서 분리 기호 문자열의 길이를 뺀 값으로 세그먼트를 분할하는 것입니다.

그런 다음 wordwrap()의 첫 번째 줄, 구분 기호 및 마지막 줄을 결합하십시오. (explode()을 사용하여 wordwrap() 출력을 줄로 나누십시오).

// 3 params: input $string, $total_length desired, $separator to use 
function truncate($string, $total_length, $separator) { 
    // The wordwrap length is half the total minus the separator's length 
    // trim() is used to prevent surrounding space on $separator affecting the length 
    $len = ($total_length - strlen(trim($separator)))/2; 

    // Separate the output from wordwrap() into an array of lines 
    $segments = explode("\n", wordwrap($string, $len)); 

    // Return the first, separator, last 
    return reset($segments) . $separator . end($segments); 
} 

그것을 밖으로 시도 : http://codepad.viper-7.com/ai6mAK

$s1 = "The quick brown fox jumped over the lazy dog"; 
$s2 = "Lorem ipsum dolor sit amet, nam id laudem aliquid. Option utroque interpretaris eu sea, pro ea illud alterum, sed consulatu conclusionemque ei. In alii diceret est. Alia oratio ei duo."; 
$s3 = "This is some other long string that ought to get truncated and leave some stuff on the end of it."; 

// Fox... 
echo truncate($s1, 30, "..."); 
// Lorem ipsum... 
echo truncate($s2, 30, "..."); 
// Other one 
echo truncate($s3, 40, "..."); 

출력을 :

The quick...the lazy dog 
Lorem ipsum...ei duo. 
This is some...on the end of it. 

공지 사항이 출력의 마지막 비트 ei duo 조금 짧은 것을. 최종 줄 wordwrap()이 반환 된 것이 전체 길이가 아니기 때문입니다. 마지막 요소의 strlen()$segments 배열에서 검사하여 일부 임계 값 (예 : $len/2)보다 작 으면 배열 요소를 explode()의 단어로 분리하고 다른 단어 앞에 추가하여 작업 할 수 있습니다 그 배열에서.

길이의 반 이상이 끝날 때까지 wordwrap()에서 두 번째 마지막 줄로 역 추적하고 단어가 튀어 나오는 문제를 해결 한 개선 된 버전입니다. 조금 더 복잡하지만 더 만족스러운 결과를 얻습니다. http://codepad.viper-7.com/mDmlL0

function truncate($string, $total_length, $separator) { 
    // The wordwrap length is half the total, minus the separator's length 
    $len = (int)($total_length - strlen($separator))/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 $total_length 
    if (strlen($end) <= $total_length/2 && count($segments) > 2) { 
    $prev = explode(' ', prev($segments)); 
    while (strlen($end) <= $total_length/2) { 
     $end = array_pop($prev) . ' ' . $end; 
    } 
    } 

    // Return the first, separator, last 
    return reset($segments) . $separator . $end; 
} 

// Produces: 
The quick...over the lazy dog 
Lorem ipsum...Alia oratio ei duo. 
This is some other...stuff on the end of it. 
+0

남자 ... 내가 대답을 기다리는 동안 나는 다시 시도했고 나는 당신의 접근에 너무 가까웠다. ** $ len **에 대한 올바른 논리가 누락되었습니다. 개인적으로, 지금 당장은 문자열에 가능한 한 가깝게 길이를 지정할 필요가 없으므로 마음에 들지 않으면 더 많은 접근 방법을보고 싶습니다. 또한, ** $ separator **에 경계 공간이 있으면 출력이 짧아집니다. –

+0

@BrunoAugusto 의도 한 길이에 가까워지기 위해 마지막 단락이 더 잘 보이는지보고 싶습니까? 분리 자 주위의 공백으로 문제를 해결하려면'strlen ($ separator)'대신'strlen (trim ($ separator))'을 사용하십시오. –

+0

그게 제가 찾고있는 것입니다. 호기심에서 벗어나서 나는 당신을 학대하지 않았 으면 좋겠지 만, 정의 된 길이에 관계없이 결과 문자열의 각 말단에 최소한의 단어가있을 수 있습니다. 단, 구분 기호가 그 주위에 추가 된 부분 문자열? –