使用 PHP 将字符串分成两半(单词感知)

发布于 2024-12-17 00:38:18 字数 558 浏览 0 评论 0原文

我正在尝试将字符串分成两半,并且它不应该在单词中间拆分。

到目前为止,我想出了以下 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

我需要在分割后保留字符串中的所有符号,例如:和/。我不明白为什么当前的代码要删除符号...如果您可以提供替代方法或修复此方法以不删除符号,我们将不胜感激:)

I'm trying to split strings in half, and it should not split in the middle of a word.

So far I came up with the following which is 99% working :

$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));

This does work, correctly splitting any string in half according to the number of words in the string. However, it is removing any symbols in the string, for example for the above example it would output :

The Quick Brown Fox Jumped
Over The Lazy Dog

I need to keep all the symbols like : and / in the string after being split. I don't understand why the current code is removing the symbols... If you can provide an alternative method or fix this method to not remove symbols, it would be greatly appreciated :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

说谎友 2024-12-24 00:38:18

在查看您的示例输出后,我注意到我们所有的示例都已关闭,如果字符串的中间位于单词内,我们会向 string1 提供较少的值,而不是提供更多的值。

例如,The Quick : Brown Fox Jumped Over The Lazy / Dog 的中间是 The Quick : Brown Fox Ju ,它位于单词的中间,第一个示例给出string2 分割词;下面的例子给出了 string1 的分割词。

在分割词上给予较少的字符串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"

Upon looking at your example output, I noticed all our examples are off, we're giving less to string1 if the middle of the string is inside a word rather then giving more.

For example the middle of The Quick : Brown Fox Jumped Over The Lazy / Dog is The Quick : Brown Fox Ju which is in the middle of a word, this first example gives string2 the split word; the bottom example gives string1 the split word.

Give less to string1 on split word

$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"

Give more to string1 on split word

$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"
寄居人 2024-12-24 00:38:18
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

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;
}

Demo: http://codepad.viper-7.com/I58gcI

坠似风落 2024-12-24 00:38:18

我知道这是一个老问题,但我有下面的代码应该可以完成所需的操作。

默认情况下,它会在中间之后第一次出现空格时分割字符串。
如果中间之后没有空格,则查找中间之前的最后一个空格。

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:

“WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW”

分割为

“WWWWWWWWWWWWWWWWWWWW”

“WWWWWWWWWWWWWWWWWWWW”

示例 2:

“WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW”

分割为

“WWWWWWWWWWWWWWWWWWWW”

“WWWWWWWWWWWWWWWWWWWW”

示例 3:

“WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW”

分割为

“WWWWWWWWWWWWWWWWWWWW”

“WWWWWWWWWWWWWWWWWWWW”

示例 4:

“WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW”

分割为

“WWWWWWWWWWWWWWWWWWWW”

“WWWWWWWWWWWWWWWWWWWW”

希望这可以帮助那里的人:)

I know this is an old question, but I have the following piece of code that should do what is needed.

It by default it splits the string on the first occurrence of a space after the middle.
If there are no spaces after the middle, it looks for the last space before the middle.

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));
}

These are examples:

Example 1:

"WWWWWWWWWW WWWWWWWWWW WWWWWWWWWW WWWWWWWWWW"

Is split as

"WWWWWWWWWW WWWWWWWWWW"

"WWWWWWWWWW WWWWWWWWWW"

Example 2:

"WWWWWWWWWWWWWWWWWWWW WWWWWWWWWW WWWWWWWWWW"

Is split as

"WWWWWWWWWWWWWWWWWWWW"

"WWWWWWWWWW WWWWWWWWWW"

Example 3:

"WWWWWWWWWW WWWWWWWWWW WWWWWWWWWWWWWWWWWWWW"

Is split as

"WWWWWWWWWW WWWWWWWWWW"

"WWWWWWWWWWWWWWWWWWWW"

Example 4:

"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"

Is split as

"WWWWWWWWWWWWWWWWWWWW"

"WWWWWWWWWWWWWWWWWWWW"

Hope this can help someone out there :)

莳間冲淡了誓言ζ 2024-12-24 00:38:18
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;
}

使用此函数将字符串拆分为半字。

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;
}

Use this function to split string into half words..

脱离于你 2024-12-24 00:38:18

与往常一样,正则表达式使开发人员免于大量繁琐的字符串操作调用和不必要的脚本膨胀。我什至会大胆地说,正则表达式模式可能比充满字符串函数的脚本更容易理解。

代码:(Demo)

function wordSafeSplit(string $text, int $pieces = 2): array
{
    $charsPerPiece = intdiv(strlen($text), $pieces);
    return preg_split(
        "~.{0,$charsPerPiece}\K\s~s",
        $text,
        $pieces
    );
}

$text = "The Quick : Brown Fox Jumped Over The Lazy / Dog";
var_export(wordSafeSplit($text));

输出:

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

实际上,我们通过计算字符串的字符数来计算字符串的中心,然后除以两个并删除所有小数位。

然后贪婪地匹配零到 $halfWay 个字符,然后用 \K 忘记这些字符,然后在最新的限定空间上分割字符串。 preg_split() 的第三个参数决定了可以生成的最大元素数量。

如果任务是将句子拆分为包含相同数量单词的两部分,则以下是如何计算单词数并使用正则表达式进行拆分:(演示

function wordSafeSplit(string $text, int $pieces = 2): array
{
    $wordsPerPiece = ceil(str_word_count($text) / $pieces);
    return preg_split(
        "~([^\w'-]*[\w'-]+[^\w' -]*){{$wordsPerPiece}}\K\s?~",
        $text,
        $pieces
    );
}

$text = "The Quick : Brown Fox Jumped Over The Lazy / Dog";
var_export(wordSafeSplit($text));

输出:

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

As usual, regex spares the developer a lot of tedious string manipulation calls and unnecessary script bloat. I'll even go out on a limb and say that the regex pattern might be easier to understand than the string function laden scripts.

Code: (Demo)

function wordSafeSplit(string $text, int $pieces = 2): array
{
    $charsPerPiece = intdiv(strlen($text), $pieces);
    return preg_split(
        "~.{0,$charsPerPiece}\K\s~s",
        $text,
        $pieces
    );
}

$text = "The Quick : Brown Fox Jumped Over The Lazy / Dog";
var_export(wordSafeSplit($text));

Output:

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

Effectively, we calculate the center of the string by counting its characters, then dividing by two and removing any decimal places.

Then greedily match zero to $halfWay number of characters, then forget those characters with \K, then split the string on the latest qualifying space. The 3rd parameter of preg_split() determines the maximum amount of elements which may be produced.

If the task is meant to split the sentence into two parts containing the same number of words, then this is how to count the words and use a regex to split: (Demo)

function wordSafeSplit(string $text, int $pieces = 2): array
{
    $wordsPerPiece = ceil(str_word_count($text) / $pieces);
    return preg_split(
        "~([^\w'-]*[\w'-]+[^\w' -]*){{$wordsPerPiece}}\K\s?~",
        $text,
        $pieces
    );
}

$text = "The Quick : Brown Fox Jumped Over The Lazy / Dog";
var_export(wordSafeSplit($text));

Output:

array (
  0 => 'The Quick : Brown Fox Jumped',
  1 => 'Over The Lazy / Dog',
)
绅刃 2024-12-24 00:38:18

我创建了一个很好的解决方案,我们不会丢失字符或单词不会被错误地剪切。

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>';

I was created a great solution, where we dont lost characters or Where the word is not cut wrongly.

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>';
过度放纵 2024-12-24 00:38:18

我尝试使用其中的几个答案,但没有得到最好的结果,所以我想我会分享解决方案。我想将标题分成两半并显示一半白色和一半绿色。

我最终将字数、文本长度、中间点和字符串的三分之一结合起来。这使我能够确保白色部分位于第三路/中路标记之间。

我希望它能帮助某人。请注意我的代码 -,&等将被视为一个词 - 它在我的测试中没有给我带来问题,但如果我发现它没有像我希望的那样工作,我会更新它。

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>';

}

I tried using a couple of these answers but didn't get the best results so I thought I would share the solution. I wanted to split my titles in half and display one half white and one half green.

I ended up combining word count, the length of the text, the half way point and a third of the string. This allowed me to make sure the white section is going to be somewhere between the third way/half way mark.

I hope it helps someone. Be aware in my code -,& etc would be considered a word - it didn't cause me issues in my testing but I will update this if I find its not working as I hope.

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>';

}
凉城 2024-12-24 00:38:18

这是类示例:

<?php

declare(strict_types=1);

namespace App\Helpers;

final class StringSplitterHelper
{
    private string $string;
    private int $stringLength;

    public function __construct(string $string)
    {
        $this->string = $string;
        $this->stringLength = mb_strlen($this->string);
    }

    public static function divide(string $string): array
    {
        return (new self($string))->toArray();
    }

    private function toArray(): array
    {
        $position = $this->getNearestSpace();

        if ($position === null) {
            return [
                $this->string,
                null,
            ];
        }

        return [
            mb_substr($this->string, 0, $position),
            mb_substr($this->string, $position + 1),
        ];
    }

    private function getNearestSpace(): ?int
    {
        $middle = intdiv($this->stringLength, 2);

        for ($i = $middle; $i >= 0; $i--) {
            if (mb_substr($this->string, $i, 1) === ' ') {
                return $i;
            }

            if (mb_substr($this->string, -$i, 1) === ' ') {
                return $this->stringLength - $i;
            }
        }

        return null;
    }
}

使用方法:

$parts = StringSplitterHelper::divide($title);

将返回 2 个元素的数组。

Here is class example:

<?php

declare(strict_types=1);

namespace App\Helpers;

final class StringSplitterHelper
{
    private string $string;
    private int $stringLength;

    public function __construct(string $string)
    {
        $this->string = $string;
        $this->stringLength = mb_strlen($this->string);
    }

    public static function divide(string $string): array
    {
        return (new self($string))->toArray();
    }

    private function toArray(): array
    {
        $position = $this->getNearestSpace();

        if ($position === null) {
            return [
                $this->string,
                null,
            ];
        }

        return [
            mb_substr($this->string, 0, $position),
            mb_substr($this->string, $position + 1),
        ];
    }

    private function getNearestSpace(): ?int
    {
        $middle = intdiv($this->stringLength, 2);

        for ($i = $middle; $i >= 0; $i--) {
            if (mb_substr($this->string, $i, 1) === ' ') {
                return $i;
            }

            if (mb_substr($this->string, -$i, 1) === ' ') {
                return $this->stringLength - $i;
            }
        }

        return null;
    }
}

The way to use it:

$parts = StringSplitterHelper::divide($title);

that will return 2 elements array.

最初的梦 2024-12-24 00:38:18

只需更改行:

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

str_word_count() 可能不会将 : 或 / 计为单词。

Just change the line:

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

str_word_count() may not count : or / as word.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文