我正在尝试将带有二进制的字符串拆分为重复字符数组。
例如,使用此函数拆分的10001101
数组将为:
$arr[0] = '1';
$arr[1] = '000';
$arr[2] = '11';
$arr[3] = '0';
$arr[4] = '1';
(我试图让自己明白,但如果你仍然不明白,我的问题与this相同,但对于PHP,而不是Python)
答案 0 :(得分:3)
你可以这样使用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
- 使文本与整个正则表达式匹配保持匹配,使此匹配为零宽度。注意:这在5.6.13之前的PHP版本中不起作用,因为有bug involving bump-along behavior with \K。
在早期版本中也适用的替代正则表达式是:
$out = preg_split('/(?<=(.))(?!\1|$)/', $in);
这使用了lookbehind而不是\K
,以使匹配为零宽度。
答案 1 :(得分:1)
<?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'
。如果您希望仅限于0
和1
,请在第二个捕获组中使用[01]
代替.
。
请记住$ m可能为空,在使用之前先检查结果是否存在,即isset($m[0])
。
答案 2 :(得分: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];
}
}
答案 3 :(得分:0)
我不会费心寻找模式中的字符串结尾。
最简洁地说,捕获第一个出现的字符,然后允许捕获的字符重复零次或多次,然后用 \K
重新开始全字符串匹配,这样就不会在爆炸中丢失任何字符。
代码:(Demo)
var_export(
preg_split('~(.)\1*\K~', '10001101', 0, PREG_SPLIT_NO_EMPTY)
);
输出:
array (
0 => '1',
1 => '000',
2 => '11',
3 => '0',
4 => '1',
)
如果您不关心正则表达式,这里有一种遍历每个字符的方法,将其与前一个字符进行比较,并有条件地将重复字符连接到一个引用变量。
代码:(Demo) ...与第一个片段的结果相同
$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);