从字符串中删除重复的连续单词
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)
如果需要在逗号和重复值之间支持任何 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';
与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);
我想从字符串中删除重复的单词(仅连续的)。
$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)
如果需要在逗号和重复值之间支持任何 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';
与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);