Разделение строк пополам (с учетом слов) с помощью PHP

Я пытаюсь разделить строки пополам, и они не должны разбиваться посередине слова.

Пока что я придумал следующее, которое работает на 99%:

$text = "The Quick : Brown Fox Jumped Over The Lazy / Dog";
$half = (int)ceil(count($words = str_word_count($text, 1)) / 2); 
$string1 = implode(' ', array_slice($words, 0, $half));
$string2 = implode(' ', array_slice($words, $half));

Это действительно работает, правильно разделяя любую строку пополам в соответствии с количеством слов в строке. Однако он удаляет любые символы в строке, например, для приведенного выше примера он выведет:

The Quick Brown Fox Jumped
Over The Lazy Dog

Мне нужно сохранить все символы, такие как: и /, в строке после разделения. Я не понимаю, почему текущий код удаляет символы ... Если вы можете предоставить альтернативный метод или исправить этот метод, чтобы не удалять символы, мы будем очень признательны :)


person Leo44    schedule 18.11.2011    source источник
comment
Я считаю требуемую логику неоднозначной. Вы пытаетесь сбалансировать количество слов в каждой половине или пытаетесь получить сбалансированное количество символов в каждой половине, не нарушая среднего слова? В этом вопросе помог бы минимальный воспроизводимый пример с набором образцов строк, которые выражают различные крайние случаи.   -  person mickmackusa    schedule 27.04.2021


Ответы (8)


Посмотрев на вывод вашего примера, я заметил, что все наши примеры отключены, мы даем меньше для string1, если середина строки находится внутри слова, а не даем больше.

Например, середина The Quick : Brown Fox Jumped Over The Lazy / Dog - это The Quick : Brown Fox Ju, которая находится в середине слова, этот первый пример дает строку2 разделенным словом; нижний пример дает строку1 разделенным словом.

Уменьшите значение строки1 для разделенного слова

$text = "The Quick : Brown Fox Jumped Over The Lazy / Dog";

$middle = strrpos(substr($text, 0, floor(strlen($text) / 2)), ' ') + 1;

$string1 = substr($text, 0, $middle);  // "The Quick : Brown Fox "
$string2 = substr($text, $middle);  // "Jumped Over The Lazy / Dog"

Добавить строку 1 при разделении слова

$text = "The Quick : Brown Fox Jumped Over The Lazy / Dog";

$splitstring1 = substr($text, 0, floor(strlen($text) / 2));
$splitstring2 = substr($text, floor(strlen($text) / 2));

if (substr($splitstring1, 0, -1) != ' ' AND substr($splitstring2, 0, 1) != ' ')
{
    $middle = strlen($splitstring1) + strpos($splitstring2, ' ') + 1;
}
else
{
    $middle = strrpos(substr($text, 0, floor(strlen($text) / 2)), ' ') + 1;    
}

$string1 = substr($text, 0, $middle);  // "The Quick : Brown Fox Jumped "
$string2 = substr($text, $middle);  // "Over The Lazy / Dog"
person Jeff Wilbert    schedule 18.11.2011
comment
Спасибо, это определенно может быть полезно выбрать, первая или вторая строка получит разделенное слово. В моем текущем проекте я хотел бы дать больше для string1, и, используя мой исходный пример `` quick brown fox '', ваш код работает должным образом, однако тестирование с другими строками, похоже, дает смешанные результаты, например, $text = "one two three four five one two three four five"; приводит к тому, что строка1 оказывается только one two three four . В любом случае я награждаю вас ответом, потому что ваш первый код выполняет работу именно так, как я просил. - person Leo44; 19.11.2011
comment
На самом деле после дальнейшего тестирования я считаю, что второй код работает так, как задумано, если только точная половина строки не является пробелом. Вероятно, это случится нечасто, так что все будет нормально :) - person Leo44; 19.11.2011
comment
Альтернативное предложение добавить больше к строке1: $ middle = strpos ($ name, '', floor (strlen ($ name) * 0.5)); - person cmc; 17.12.2014
comment
@ Jeff-Wilbert, есть ли шанс, что ты поможешь мне поподробнее? мой вопрос размещен по адресу: stackoverflow.com/questions/42505200/ - person MitchellK; 28.02.2017

function split_half($string, $center = 0.4) {
        $length2 = strlen($string) * $center;
        $tmp = explode(' ', $string);
        $index = 0; 
        $result = Array('', '');
        foreach($tmp as $word) {
            if(!$index && strlen($result[0]) > $length2) $index++;
            $result[$index] .= $word.' ';
        }
        return $result;
}

Демонстрация: http://codepad.viper-7.com/I58gcI

person Peter    schedule 18.11.2011
comment
Спасибо за демонстрацию функции, похоже, она работает так, как задумано. - person Leo44; 19.11.2011
comment
Все остальные, кроме этого, у меня не работали. Я сделал небольшое изменение, которое решает проблему только с двумя словами, а второе - длиннее, добавив if(count($tmp) < 3) { return $tmp; } после explode - person B-Stewart; 01.09.2017
comment
В этом ответе отсутствует образовательное объяснение. - person mickmackusa; 27.04.2021

Я знаю, что это старый вопрос, но у меня есть следующий фрагмент кода, который должен делать то, что необходимо.

По умолчанию он разбивает строку при первом появлении пробела после середины. Если после середины нет пробелов, ищется последний пробел перед серединой.

function trim_text($input) {
    $middle = ceil(strlen($input) / 2);
    $middle_space = strpos($input, " ", $middle - 1);

    if ($middle_space === false) {
        //there is no space later in the string, so get the last sapce before the middle
        $first_half = substr($input, 0, $middle);
        $middle_space = strpos($first_half, " ");
    }

    if ($middle_space === false) {
        //the whole string is one long word, split the text exactly in the middle
        $first_half = substr($input, 0, $middle);
        $second_half = substr($input, $middle);
    }
    else {
        $first_half = substr($input, 0, $middle_space);
        $second_half = substr($input, $middle_space);
    }
        return array(trim($first_half), trim($second_half));
}

Вот примеры:

Пример 1:

"WWWWWWWWWW WWWWWWWWWW WWWWWWWWWW WWWWWWWWWW"

Разделен как

"WWWWWWWWWW WWWWWWWWWW"

"WWWWWWWWWW WWWWWWWWWW"

Пример 2:

"WWWWWWWWWWWWWWWWWWW WWWWWWWWWW WWWWWWWWWW"

Разделен как

"WWWWWWWWWWWWWWWWWWWW"

"WWWWWWWWWW WWWWWWWWWW"

Пример 3:

"WWWWWWWWWW WWWWWWWWWW WWWWWWWWWWWWWWWWWWW"

Разделен как

"WWWWWWWWWW WWWWWWWWWW"

"WWWWWWWWWWWWWWWWWWW"

Пример 4:

"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"

Разделен как

"WWWWWWWWWWWWWWWWWWW"

"WWWWWWWWWWWWWWWWWWW"

Надеюсь, это поможет кому-то :)

person Rickus Harmse    schedule 07.06.2019

function split_half($string){
$result= array();
$text = explode(' ', $string);
$count = count($text);
$string1 = '';
$string2 = '';
if($count > 1){
    if($count % 2 == 0){
        $start = $count/2;
        $end = $count;
        for($i=0; $i<$start;$i++){
            $string1 .= $text[$i]." ";
        }
        for($j=$start; $j<$end;$j++){
            $string2 .= $text[$j]." ";
        }           
    $result[] = $string1;
    $result[] = $string2;
    }
    else{
        $start = round($count/2)-1;
        $end = $count;
        for($i=0; $i<$start;$i++){
            $string1 .= $text[$i]." ";
        }
        for($j=$start; $j<$end;$j++){
            $string2 .= $text[$j]." ";
        }           
    $result[] = $string1;
    $result[] = $string2;

    }
}
else{
    $result[] = $string;
}
return $result;
}

Используйте эту функцию, чтобы разделить строку на полуслова ..

person Divyesh Prajapati    schedule 19.07.2013

Как обычно, регулярное выражение избавляет разработчика от множества утомительных вызовов манипулирования строками и ненужного раздувания скриптов. Я даже рискну и скажу, что шаблон регулярного выражения может быть легче понять, чем скрипты, загруженные строковыми функциями.

Код: (Демо)

$text = "The Quick : Brown Fox Jumped Over The Lazy / Dog";
$halfWay = (int)(strlen($text) / 2);
var_export(
    preg_split(
        '~.{0,' . $halfWay . '}\K\s~s',
        $text,
        2
    )
);

Выход:

array (
  0 => 'The Quick : Brown Fox',
  1 => 'Jumped Over The Lazy / Dog',
)

Фактически, мы вычисляем центр строки, считая ее символы, затем деля их на два и удаляя все десятичные знаки.

Затем жадно сопоставьте ноль с $halfWay количеством символов, затем забудьте эти символы с помощью \K, затем разделите строку на последнем подходящем месте. Третий параметр preg_split() определяет максимальное количество элементов, которое может быть произведено.

person mickmackusa    schedule 27.04.2021
comment
Мне нравится ваше решение, его тоже можно разделить на несколько частей. Разделится на 3 части с неплохим результатом. - person PeterM; 29.06.2021

Я создал отличное решение, где мы не теряем символы или где слово не вырезано неправильно.

function split_title_middle ( $title ) {
    $title = strip_tags( $title );
    $middle_length = floor( strlen( $title ) / 2 );
    $new_title = explode( '<br />', wordwrap( $title, $middle_length, '<br />') );
    if (isset( $new_title[2] ) ) {
        $new_title[1] .= ' ' . $new_title[2];
        unset( $new_title[2] );
    }

    return $new_title;
 }

// how to use
$title = split_title_middle( $title );
echo $title[0] . '<strong>' . $title[1] . '</strong>';
person Richelly Italo    schedule 17.02.2017

Я попытался использовать пару из этих ответов, но не получил наилучших результатов, поэтому подумал, что поделюсь решением. Я хотел разделить свои заголовки пополам и отобразить половину белыми и половину зелеными.

В итоге я объединил количество слов, длину текста, половину пути и треть строки. Это позволило мне убедиться, что белая секция будет где-то между отметкой третьего пути / середины пути.

Надеюсь, это кому-то поможет. Имейте в виду, что в моем коде и т. Д. Будут считаться словом - это не вызывало у меня проблем при тестировании, но я обновлю это, если обнаружу, что он не работает так, как я надеюсь.

public function splitTitle($text){

    $words = explode(" ",$text);
    $strlen = strlen($text);
    $halfwaymark = ceil($strlen/2);
    $thirdwaymark = ceil($strlen/3);

    $wordcount = sizeof($words);
    $halfwords = ceil($wordcount/2);
    $thirdwords = ceil($wordcount/3);

    $string1 ='';
    $wordstep = 0;
    $wordlength = 0;


    while(($wordlength < $wordcount && $wordstep < $halfwords) || $wordlength < $thirdwaymark){
        $string1 .= $words[$wordstep].' ';
        $wordlength = strlen($string1);
        $wordstep++;
    }

    $string2 ='';
    $skipspace = 0;
    while(($wordstep < $wordcount)){
        if($skipspace==0) {
            $string2 .= $words[$wordstep];
        } else {
            $string2 .= ' '.$words[$wordstep];
        }
        $skipspace=1;
        $wordstep++;
    }

    echo $string1.' <span class="highlight">'.$string2.'</span>';

}
person UrbanwarfareStudios    schedule 18.05.2020

Просто измените строку:

$half = (int)ceil(count($words = (count(explode(" ",$text))) / 2);

str_word_count() не может считаться: или / как слово.

person Ariful Islam    schedule 18.11.2011
comment
К сожалению, это не сработало, просто были созданы пустые строки. Также в конце отсутствует закрывающая скобка. Но спасибо за попытку :) - person Leo44; 19.11.2011