PHP字符串交叉,贪婪地从左从右剥离

发布于 2024-11-24 10:09:19 字数 1992 浏览 1 评论 0原文

我希望从另一个字符串 $right 的左侧剥离一个字符串 $left。给定:

$left  = 'alpha beta gamma';
$right = 'beta gamma delta';

期望的输出是:

string(6) " delta"

现在,我已经完成了这一点。我写了一个函数,来准确地实现这一点:

function strip_left_from_right($left, $right){
    for($i = 0, $m = strlen($left); $i <= $m; $i++){
        $needle = substr($left, -$i);
        if(substr($right, 0, strlen($needle)) == $needle){
            return substr($right, strlen($needle));
        }
    }
}

并且它工作得很好。不过,我希望它是“贪婪的”,尽可能多地使用 $left 字符串。例如:

$left  = "foofoofoofoo";
$right = "foofoofoobar";

// desired output
string(3) "bar"

// actual output
string(9) "foofoobar"

本质上我的问题有两个方面:

  1.执行“贪婪”匹配的最佳方式是什么? (假设我继续使用此代码

并且可能更重要;

  2.有没有更好的(非迭代,串联使用的一组核心函数)方法来完成此任务?


我采用的解决方案,感谢@Yoshi 让我的大脑朝着这个方向发展:

function intersect_split($left, $right, $greedy = true){
    for($i = 0, $m = strlen($left); $i <= $m; $i++){
        $chunk = substr($left, $i * (int) ($greedy ?: -1));
        if(substr($right, 0, strlen($chunk)) == $chunk){
            return array(
                (string) substr($left, 0, $m - strlen($chunk)),
                (string) substr($right, strlen($chunk)),
            );
        }
    }
    return array($left, $right);
}

$left  = 'foo bar bar bar bar';
$right = 'bar bar bar bar baz';

var_dump( intersect_split($left, $right, true) );
var_dump( intersect_split($left, $right, false) );

产生:

array(2) {
  [0]=>
  string(4) "foo "
  [1]=>
  string(4) " baz"
}
array(2) {
  [0]=>
  string(16) "foo bar bar bar "
  [1]=>
  string(16) " bar bar bar baz"
}

所以现在我基本上在 $left 参数右侧和 $right 参数左侧的相交匹配处分割字符串,生成前导和尾随字符串在一个数组中。 $greedy 产生明显的结果差异。

I'm looking to strip a string, $left from the left of another string, $right. Given:

$left  = 'alpha beta gamma';
$right = 'beta gamma delta';

The desired output would be:

string(6) " delta"

Now, I've sort of accomplished this. I've written a function, to achieve this exactly:

function strip_left_from_right($left, $right){
    for($i = 0, $m = strlen($left); $i <= $m; $i++){
        $needle = substr($left, -$i);
        if(substr($right, 0, strlen($needle)) == $needle){
            return substr($right, strlen($needle));
        }
    }
}

And it works fine. However I want it to be be "greedy", using as much of the $left string as possible. For instance:

$left  = "foofoofoofoo";
$right = "foofoofoobar";

// desired output
string(3) "bar"

// actual output
string(9) "foofoobar"

Essentially my question is two-fold;

  1. What would be the best way to perform a "greedy" match? (given I continue with this code)

And probably more important;

  2. Is there a better (non-iterative, set of core functions used in tandem) way to accomplish this?


The solution I went with, thanks to @Yoshi for getting my brain in that direction:

function intersect_split($left, $right, $greedy = true){
    for($i = 0, $m = strlen($left); $i <= $m; $i++){
        $chunk = substr($left, $i * (int) ($greedy ?: -1));
        if(substr($right, 0, strlen($chunk)) == $chunk){
            return array(
                (string) substr($left, 0, $m - strlen($chunk)),
                (string) substr($right, strlen($chunk)),
            );
        }
    }
    return array($left, $right);
}

$left  = 'foo bar bar bar bar';
$right = 'bar bar bar bar baz';

var_dump( intersect_split($left, $right, true) );
var_dump( intersect_split($left, $right, false) );

Produces:

array(2) {
  [0]=>
  string(4) "foo "
  [1]=>
  string(4) " baz"
}
array(2) {
  [0]=>
  string(16) "foo bar bar bar "
  [1]=>
  string(16) " bar bar bar baz"
}

So now I essentially split the string at an intersecting match of the right of the $left argument and left of the $right argument, producing the leading and trailing strings in an array. $greedy produces the obvious difference in results.

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

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

发布评论

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

评论(1

只等公子 2024-12-01 10:09:22

不是最佳的,但至少它完成了工作:

function helper($left, $right) {
    $match = '';

    for ($i = strlen($left) - 1; $i >= 0; $i -= 1) {
        $chunk = substr($left, $i);
        $len = strlen($chunk);
        if (substr($right, 0, $len) == $chunk && $len > strlen($match)) {
            $match = $chunk;
        }
    }

    return substr($right, strlen($match));
}

echo helper('alpha beta gamma', 'beta gamma delta'); // output " delta"
echo helper('foofoofoofoo', 'foofoofoobar'); // output "bar"

Not optimal, but at least it does the job:

function helper($left, $right) {
    $match = '';

    for ($i = strlen($left) - 1; $i >= 0; $i -= 1) {
        $chunk = substr($left, $i);
        $len = strlen($chunk);
        if (substr($right, 0, $len) == $chunk && $len > strlen($match)) {
            $match = $chunk;
        }
    }

    return substr($right, strlen($match));
}

echo helper('alpha beta gamma', 'beta gamma delta'); // output " delta"
echo helper('foofoofoofoo', 'foofoofoobar'); // output "bar"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文