从字符串中删除重复的连续单词

Remove repetitve Consecutive words from string

我想从字符串中删除重复的单词(仅连续的)。

$str = 'abc,def,fgh,fgh,xna,fgh,xyz,xyz,xyz,tr,tr,xna';

我想要的输出字符串是:

abc,def,fgh,xna,fgh,xyz,tr,xna

我可以在 php 中得到我想要的结果:

$ip = explode(',', $str);
$op = [];$last = null;
for($i=0;$i<count($ip);$i++){
    if ($last == $ip[$i]) {
        continue;
    }
    $op[]=$last=$ip[$i];
}
$ip = implode(',', $op);

但一直在寻找正则表达式方法。到目前为止,我已经更接近这两个正则表达式了:

$after = preg_replace('/(?:^|,)([^,]+)(?=.*,(?:,|$))/m', '', $str);
output : abc,def,fgh,xyz,tr,xna

$after = preg_replace('/([^,]+)(,[ ]*)+/m', '', $str);
output : abc,degh,fgh,xna,fgh,,,xna
$after = preg_replace('/(?<=^|,)([^,]+)(,\s*)+/', '', $str);

P.S。如果在 , 之后没有空格期望值,你可以从上面的正则表达式中去掉 \s*。我刚刚查看了您的 [ ]* 并认为您可能有空格。

你应该使用

preg_replace('~(?<![^,])([^,]+)(?:,)+(?![^,])~', '', $str)

regex demo

如果需要在逗号和重复值之间支持任何 0 个或多个空白字符,add \s*0 个或更多空白)模式在 </code>.</p> <p><strong>详情</strong></p> <ul> <li><code>(?<![^,]) - 字符串或逗号以外的任何字符的开头

  • ([^,]+) - 第 1 组:逗号以外的任何一个或多个字符
  • (?:,)+ - 一个或多个逗号序列和组 1
  • 中的值
  • (?![^,]) - 字符串结尾或逗号以外的字符。
  • 用strtok迭代,只粘合与上一个不同的部分:

    <?php
    
    $str = 'abc,def,fgh,fgh,xna,fgh,xyz,xyz,xyz,tr,tr,xna';
    
    $out = $last = strtok($str, ',');
    while($current = strtok(','))
        if($current !== $last)
            $out .= ',' . ($last = $current);
    
    echo $out;
    

    输出:

    abc,def,fgh,xna,fgh,xyz,tr,xna
    

    我会这样解决:

    $after = preg_replace('/(?<=,|^)([^,]+)\K(,)+(?=,|$)/', '', $str);
    

    这将输出 abc,def,fgh,xna,fgh,xyz,tr,xna.

    它的作用:

    • (?<=,|^) 查看是逗号还是字符串在
    • 之前开始
    • ([^,]+) 匹配逗号以外的任何内容(搜索模式)
    • \K 重置内部游标和 "forgets" 之前的内容(例如,它不再算作匹配)
    • (,)+ 匹配第一个定义的搜索模式的多次出现
    • (?=,|$) 查看下一个字符是否再次为逗号或者字符串是否结束

    所以这个想法是,select 重复任何模式(仅重复)并用任何东西替换它们。

    更新:

    通过添加 (?=,|$) 修复了模式。否则这个测试输入会失败 并完全杀死 xna 部分。

    $str = 'bc,abc,abc,abc,def,fgh,fgh,xna,fgh,xyz,xyz,xyz,tr,tr,xna,xna,xnabc';
    

    在这里测试:https://regex101.com/r/Yv1htV/3

    array_reduce:

    $arr = explode(',', $str);
    $prev = array_shift($arr);
    $result = array_reduce($arr, function($c, $i) use (&$prev) {
        if ($prev==$i) return $c;
        $prev=$i;
        return "$c,$i";
    }, $prev);