Java:String.replaceAll(正则表达式,替换);

Java: String.replaceAll(regex, replacement);

我有一串以逗号分隔的用户 ID,我想从字符串中 eliminate/remove 特定的用户 ID。

我已经关注字符串的可能性并期待结果

int elimiateUserId = 11;

String css1 = "11,22,33,44,55";
String css2 = "22,33,11,44,55";
String css3 = "22,33,44,55,11";
// The expected result in all cases, after replacement, should be:
// "22,33,44,55"

我尝试了以下方法:

String result = css#.replaceAll("," + elimiateUserId, "");  // # =  1 or 2 or 3
result = css#.replaceAll(elimiateUserId + "," , "");

这个逻辑在 css3 的情况下失败。请建议我解决此问题的正确方法。

注意:我正在使用 Java 7

我查看了以下帖子,但找不到任何解决方案:

尝试将(^(11)(?:,))|((?<=,)(11)(?:,))|(,11$)表达为replaceAll:

final String regexp = MessageFormat.format("(^({0})(?:,))|((?<=,)({0})(?:,))|(,{0}$)", elimiateUserId)
String result = css#.replaceAll(regexp, "") //for all cases.  

这是一个例子: https://regex101.com/r/LwJgRu/3

您可以在 Java 8:

中使用 Stream API
int elimiateUserId = 11;
String css1 = "11,22,33,44,55";

String css1Result = Stream.of(css1.split(","))
    .filter(value -> !String.valueOf(elimiateUserId).equals(value))
    .collect(Collectors.joining(","));

// css1Result = 22,33,44,55

这应该有效

replaceAll("(11,|,11)", "")

至少当你能保证没有311的时候,或者,113左右

如果你想使用正则表达式,你可以使用(记得正确转义为 java 字符串文字)

,\b11\b|\b11\b,

这将确保 11 不会由于单词边界而被匹配为另一个数字的一​​部分,并且只会匹配和删除一个逗号(如果存在两个逗号)。

您可以一次使用两个替换,例如:

int elimiateUserId = 11;
String result = css#.replace("," + elimiateUserId , "").replace(elimiateUserId + ",", "");

如果您的字符串类似于 ,11,则第一个替换会将其替换为空字符串
如果您的字符串类似于 11,,则第二个替换会将其替换为空

结果

11,22,33,44,55      ->     22,33,44,55
22,33,11,44,55      ->     22,33,44,55
22,33,44,55,11      ->     22,33,44,55

ideone demo

你可以像这样构建一个正则表达式

^11,|,11\b

将匹配字符串开头的 11, (^11,) 或 (|) ,11 后面没有任何其他单词 char (,11\b).

参见regex demo

int elimiate_user_id = 11;
String pattern = "^" + elimiate_user_id + ",|," + elimiate_user_id + "\b";
System.out.println("11,22,33,44,55,111".replaceAll(pattern, "")); // => 22,33,44,55,111
System.out.println("22,33,11,44,55,111".replaceAll(pattern, "")); // => 22,33,44,55,111 
System.out.println("22,33,44,55,111,11".replaceAll(pattern, "")); // => 22,33,44,55,111

Java demo

我认为维护一个白名单比较安全,然后将其作为参考进行进一步的更改。

List<String> whitelist = Arrays.asList("22", "33", "44", "55");
String s = "22,33,44,55,11";
String[] sArr = s.split(",");
StringBuilder ids = new StringBuilder();
for (String id : sArr) {
    if (whitelist.contains(id)) {
        ids.append(id).append(", ");
    }
}
String r = ids.substring(0, ids.length() - 2);
System.out.println(r);

试试这个:

String result = css#.replaceAll("," + elimiateUserId, "")
             .replaceAll(elimiateUserId + "," , "");
String result = css#.replaceAll("," + eliminate_user_id + "\b|\b" + eliminate_user_id + ",", '');

这里的正则表达式是:

,     A leading comma.
eliminate_user_id  I assumed the missing 'n' here was a typo.
\b    Word boundary: word/number characters end here.
|     OR
\b    Word boundary: word/number characters begin here.
eliminate_user_id again.
,     A trailing comma.

单词边界标记,匹配 "word" 的开头或结尾,是这里的魔法。这意味着 11 将匹配这些字符串:

11,22,33,44,55
22,33,11,44,55
22,33,44,55,11 

但不是这些字符串:

111,112,113,114
411,311,211,111

不过,还有一种更简洁的方法:

String result = css#.replaceAll("(,?)\b" + eliminate_user_id + "\b(?(1)|,)", "");

这里的正则表达式是:

(     A capturing group - what's in here, is in group 1.
,?    An optional leading comma.
)     End the capturing group.
\b    Word boundary: word/number characters begin here.
eliminate_user_id  I assumed the missing 'n' here was a typo.
\b    Word boundary: word/number characters end here.
(?(1) If there's something in group 1, then require...
|     ...nothing, but if there was nothing, then require...
,     A trailing comma.
)     end the if.

此处的 "if" 部分有点不寻常 - 您可以在此处找到有关正则表达式条件的更多信息:http://www.regular-expressions.info/conditional.html

我不确定 Java 是否支持正则表达式条件。这里的一些帖子 (Conditional Regular Expression in Java?) 表明它没有 :(


旁注:为了性能,如果列表很长并且要执行的删除操作非常多,最明显的选择是 运行 上面一行中的每个要删除的数字:

String css = "11,22,33,44,55,66,77,88,99,1010,1111,1212,...";
Array<String> removals = ["11", "33", "55", "77", "99", "1212"];
for (i=0; i<removals.length; i++) {
  css = css.replaceAll("," + removals[i] + "\b|\b" + eliminate_user_id + ",", "");
}

(代码未测试:此处无法访问 Java 编译器)

这将足够快(从 n 个 ID 的字符串中删除 m 的最坏情况大约为 O(m*n)),但我们也许可以做得更好。

一种是将正则表达式构建为 \b(11,42,18,13,123,...etc)\b - 即让正则表达式同时搜索所有要删除的 ID。从理论上讲,这种缩放比例更差一些,在每种情况下都以 O(m*n) 缩放,而不是最坏的情况,但实际上应该快得多。

String css = "11,22,33,44,55,66,77,88,99,1010,1111,1212,...";
Array<String> removals = ["11", "33", "55", "77", "99", "1212"];
String removalsStr = String.join("|", removals);
css = css.replaceAll("," + removalsStr + "\b|\b" + removalsStr + ",", "");

但另一种方法可能是构建长字符串中 ID 的哈希表,然后从哈希表中删除所有 ID,然后将剩余的哈希表键连接回字符串。由于哈希表查找对于稀疏哈希表来说实际上是 O(1),这使得这个规模与 O(n) 成正比。不过,这里的权衡是该哈希表的额外内存。

(如果没有 java 编译器,我不认为我可以做这个版本。我不会推荐这种方法,除非你有一个 VAST(数千)ID 列表要删除,无论如何,因为这将是更丑陋和更复杂的代码。

如果您需要使用 Regex 的解决方案,那么下面的方法非常有效。

    int elimiate_user_id = 11;

    String css1 = "11,22,33,44,55";
    String css2 = "22,33,11,44,55";   
    String css3 = "22,33,44,55,11";

    String resultCss=css1.replaceAll(elimiate_user_id+"[,]*", "").replaceAll(",$", "");

我处理您想要的所有类型的输入。