[英]Removing all occurrences of the specified substring, even overlapping ones
例如,源字符串是“appleappleapplebanana”,我想删除的模式是“appleapple”。
我希望它删除所有“appleapple”,即使它们重叠,这样只剩下“banana”。
appleappleapplebanana
^^^^^^^^^^ <-first occurrence
^^^^^^^^^^ <-second occurrence
如果我使用 replaceAll,结果是“applebanana”,因为删除第一个后,剩下的部分只是“applebanana”。
预期成绩:
输入 | 图案 | 结果 |
---|---|---|
“苹果香蕉” | “苹果苹果” | “香蕉” |
“苹果香蕉” | “苹果苹果” | “香蕉” |
“苹果苹果香蕉” | “苹果苹果” | “香蕉” |
“苹果香蕉” | “苹果苹果” | “苹果香蕉” |
“aaabbbaaabbbaaa” | “aaabbbaaa” | “”(空字符串) |
我需要处理任意输入模式,因此仅使用replace("apple")
是行不通的。
虽然我对此有一个想法:
但是,我想知道是否有更好的(现成的)方法来实现这一目标。
我最终使用上面的想法制作了自己的 function,因为似乎没有公共库或包似乎支持此功能。
起初这个问题有点令人困惑。 更新后,我认为最好提供的示例来说明问题是匹配aaabbbaaabbbaaa
中的“模式” aaabbbaaa
。
aaabbbaaabbbaaa
aaabbbaaa
aaabbbaaa
^-^ < overlapping part
^-------------^ < match this part: 'aaa' is overlapping
如果正则表达式中可以使用“模式”字符串的长度,则可以使用后视:
.{1,9}(?<=aaabbbaaa)
这个正则表达式(演示)将匹配从一个到字符串长度的字符,只要aaabbbaaa
在后面。 所以这将匹配aaabbbaaa
但也匹配bbbaaa
,因为最后一个a
之前也有aaabbbaaa
,并且由于长度限制,它不会跳过任何其他 substring。它还将匹配aaabbbaaaaaabbbaaa
中的非重叠,但将例如ccc
留在aaabbbaaacccaaabbbaaa
中。
tio.run 上的 Java 演示包含长度:
String regex = ".{1," + pat.length() + "}(?<=" + pat + ")";
Pattern p = Pattern.compile(regex);
String result = p.matcher(str).replaceAll("");
对于较长的输入,可以更有效地添加前瞻以开始匹配并将后视部分包装到重复组中,至少重复一次:
(?=aaabbbaaa)(?:.{1,9}(?<=aaabbbaaa))+
这几乎可以将性能提高一倍(演示),但与没有 .相比,较短的字符串效率较低。 此外,如果输入包含非单词字符,您可以使用\w
(单词字符)代替点。
从技术上讲,这是重叠的。
appleapple
appleappleappleapple
appleapple
而且,这是重复的。
appleapple
appleapple
appleapple
虽然,您可以将后者称为重叠.
从本质上讲,这不是被认为具有重复质量的模式的属性。
在那一点上它是固有的——多余的——它只是一个描述。
除了String#replace之外,还有String#replaceAll 。
它使用正则表达式模式作为第一个参数。
您可以使用以下模式来替换重叠的重复值。
(apple)\1+
replaceAll("(apple)\\1+", "")
我不确定是否有办法使用单一模式删除重叠值。
我想这会复杂得多。
您提到“...将相应字符标记为‘待删除’” 。
这很可能是删除真正重叠值的合乎逻辑的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.