如何在PHP中通过重复的字符拆分字符串?

6
我将尝试将一个二进制字符串拆分成由重复字符组成的数组。
例如,使用此函数拆分10001101将得到以下数组:
    $arr[0] = '1';
    $arr[1] = '000';
    $arr[2] = '11';
    $arr[3] = '0';
    $arr[4] = '1';

我尝试讲得清楚,但如果你还是不明白,我的问题与这个类似,只不过是针对PHP而不是Python。


1
尝试使用 https://github.com/CHH/itertools/blob/master/lib/itertools.php 这个工具,它是从你所引用的Python到PHP移植的相同工具。 - sodhancha
4个回答

5
您可以像这样使用preg_split

示例:

$in = "10001101";
$out = preg_split('/(.)(?!\1|$)\K/', $in);

print_r($out);

输出:

Array
(
    [0] => 1
    [1] => 000
    [2] => 11
    [3] => 0
    [4] => 1
)

正则表达式:

  • (.) - 匹配单个字符并捕获它
  • (?!\1|$) - 查看下一个位置,如果它不与刚刚找到的字符相同且不是字符串的结尾,则匹配。
  • \K - 保留迄今为止匹配的文本,使此匹配为零宽度。

注意:在PHP版本5.6.13之前,这种方法无法工作,因为\K存在漏洞


另一种在早期版本中也可用的正则表达式是:

$out = preg_split('/(?<=(.))(?!\1|$)/', $in);

为了使匹配的宽度为零,这里使用的是回顾后发 (lookbehind) 而非 \K


1
啊哇,我慢了几秒钟。这是我的代码: preg_match_all("@(\w)\\1*@", $arg, $matches); print_r($matches[0]);``` - Sean Johnson
@paul:有些问题...看一下最后一个元素 Array ( [0] => 1 [1] => 000 [2] => 11 [3] => 01 ) - Subin Thomas
@SeanJohnson 工作得非常完美,谢谢。答案本身不起作用。 - R__

2
<?php
$s = '10001101';
preg_match_all('/((.)\2*)/',$s,$m);
print_r($m[0]);
/*
Array
(
    [0] => 1
    [1] => 000
    [2] => 11
    [3] => 0
    [4] => 1
)
*/
?>

匹配重复的连续字符序列,长度至少为1。正则表达式将主题字符存储在第二个捕获组中((.),作为$m [1]存储),而第一个捕获组包含整个重复序列(((.)\2*),作为$m [0]存储)。使用preg_match_all函数在整个字符串上进行全局匹配。这可以应用于任何字符串,例如'aabbccddee'。如果您只想限制为01,则在第二个捕获组中使用[01]代替.
请注意,$m可能为空,因此在使用之前,请先检查结果是否存在,即isset($m[0])

0
我在考虑这样的代码。这段代码没有经过测试,我直接写在注释里,所以可能会有一些错误,你可以进行调整。
$chunks = array();
$index = 0;
$chunks[$index] = $arr[0];
for($i = 1; $i < sizeof($arr) - 1; $i++) {
  if( $arr[$i] == $arr[$i-1] ) {
    $chunks[$index] .= $arr[$i];
  } else {
    $index++;
    $chunks[$index] = $arr[$i];
  }
}

0

我不会费心在模式中查找字符串的结尾。

最简洁的方法是先捕获第一个出现的字符,然后允许对捕获的字符进行零次或多次重复,随后使用 \K 重新开始完整字符串匹配,这样不会在匹配过程中丢失任何字符。

代码:(演示)

var_export(
    preg_split('~(.)\1*\K~', '10001101', 0, PREG_SPLIT_NO_EMPTY)
);

输出:

array (
  0 => '1',
  1 => '000',
  2 => '11',
  3 => '0',
  4 => '1',
)

如果您不使用正则表达式,以下是一种逐个字符迭代的方法,将其与前一个字符进行比较,并有条件地将重复字符连接到参考变量。

代码:(演示)...与第一个片段相同的结果

$array = [];
$lastChar = null;
foreach (str_split('10001101') as $char) {
    if ($char !== $lastChar) {
        unset($ref);
        $array[] = &$ref;
        $ref = $char;
        $lastChar = $char;
    } else {
        $ref .= $char;
    }
}
var_export($array);

@R__,我看到你自从我回答后就一直在线。你有没有接受我的答案的可能性,这样研究人员可以更轻松地找到一个完善的解决方案呢? - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接