繁体   English   中英

String.replace() 不替换所有出现

[英]String.replace() not replacing all occurrences

我有一个很长的字符串,看起来与此类似。

355,356,357,358,359,360,361,382,363,364,365,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,368,369,313,370,371,372,373,374,375,376,377,378,379,380,381,382,382,382,382,382,382,383,384,385,380,381,382,382,382,382,382,386,387,388,389,380,381,382,382,382,382,382,382,390,391,380,381,382,382,382,382,382,392,393,394,395,396,397,398,399,....

当我尝试使用以下代码从字符串中删除数字 382 时。

String str = "355,356,357,358,359,360,361,382,363,364,365,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,368,369,313,370,371,372,373,374,375,376,377,378,379,380,381,382,382,382,382,382,382,383,384,385,380,381,382,382,382,382,382,386,387,388,389,380,381,382,382,382,382,382,382,390,391,380,381,382,382,382,382,382,392,393,394,395,396,397,398,399,...."
str = str.replace(",382,", ",");

但似乎并非所有事件都被替换。 原来出现次数超过 3000 次的字符串在替换后仍然出现了大约 630 次。

String.replace() 的能力是否有限? 如果是这样,是否有可能实现我需要的方法?

我认为问题是你的第一个参数replace() ,特别是382之前之后的逗号(,)。如果你有“382,382,383”,你将只匹配内部“,382”,并留下最初的一个。 尝试:

str.replace("382,", "");

虽然在最后它将无法匹配“382”,因为它之后没有逗号。

完整的解决方案可能需要两个方法调用:

str = str.replace("382", "");  // Remove all instances of 382
str.replaceAll(",,+", ",");    // Compress all duplicates, triplicates, etc. of commas

这结合了两种方法:

str.replaceAll("382,?", "");  // Remove 382 and an optional comma after it. 

注意:如果382在结尾,则后两种方法都会留下尾随逗号。

您还需要替换尾随逗号(如果存在,如果列表中的最后一个则不会):

str = str.replaceAll("\\b382,?", "");

注意\\b字边界以防止匹配"-,1382,-"

以上将转换:

382,111,382,1382,222,382

至:

111,1382,222

尝试这个

str = str.replaceAll(",382,", ",");

首先,删除匹配字符串中的前一个逗号。 然后,通过使用java正则表达式将逗号替换为单个逗号来删除重复的逗号。

 String input = "355,356,357,358,359,360,361,382,363,364,365,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,368,369,313,370,371,372,373,374,375,376,377,378,379,380,381,382,382,382,382,382,382,383,384,385,380,381,382,382,382,382,382,386,387,388,389,380,381,382,382,382,382,382,382,390,391,380,381,382,382,382,382,382,392,393,394,395,396,397,398,399";
    String result = input.replace("382,", ","); // remove the preceding comma
    String result2 = result.replaceAll("[,]+", ","); // replace duplicate commas

    System.out.println(result2);

正如戴夫已经说过的,问题是你的模式重叠了。 在字符串"...,382,382,..."有两次出现",382,"

"...,382,382,..."
    -----         first occurrence
        -----     second occurrence

这两个匹配项在逗号处重叠,因此Java只能替换其中一个。 当找到事件时,它还没有看到你用什么替换模式,因此当替换第一个匹配项被逗号替换时",382,"它不会看到新的",382,"出现。

如果您的数据已知不包含超过3位数的数字,那么您可能会:

str.replace("382,", "");

然后作为特例处理最后的事件。 但是如果你的数据可以包含大数字,那么"...,1382,..."将被"...,1,..."取代"...,1,..."这可能不是你想要的。

以下是两个没有上述问题的解决方案:

首先,只需重复更换,直到不再发生变化:

String oldString = str;
str = str.replace(",382,", ",");
while (!str.equals(oldString)) {
    oldString = str;
    str = str.replace(",382,", ",");
}

之后,您将必须处理字符串末尾可能出现的事件。

其次,如果你有Java 8,你可以自己做更多的工作并使用Java流:

str = Arrays.stream(str.split(","))
    .filter(s -> !s.equals("382"))
    .collect(Collectors.joining(","));

这首先将字符串拆分为“,”,然后过滤掉所有等于“382”的字符串,然后将剩余的字符串再次与“,”之间连接起来。

(两个代码段都未经过测试。)

传统方式:

    String str = ",abc,null,null,0,0,7,8,9,10,11,12,13,14";
    String newStr = "", word = "";
    for (int i=0; i<str.length(); i++) {
        if (str.charAt(i) == ',') {
            if (word.equals("null") || word.equals("0"))
                word = "";
            newStr += word+",";
            word = "";
        } else {
            word += str.charAt(i);
            if (i == str.length()-1)
                newStr += word;
        }
    }
    System.out.println(newStr);

输出:,abc,,,,,7,8,9,10,11,12,13,14

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM