java字符串替换字符

huangapple go评论70阅读模式
英文:

java String replace characters

问题

我需要你的帮助解决一个棘手的问题。
我有一个如下的 映射(map)

Map<Integer, String> ruleMap = new HashMap<>();
ruleMap.put(1, "A");
ruleMap.put(12, "Test - 12");
ruleMap.put(1012, "Test Metadata 12 A");

然后我有一个 规则(rule),我要在其中分离出 ID 并将它们收集到一个列表中。通过迭代列表,我将其中的 ID 替换为映射中相应的值。

代码:

String rule = "1 AND 12 OR 1012 AND 12 or 1012";

List<String> idList = new ArrayList<>();

Pattern p = Pattern.compile("[0-9]+");
Matcher m = p.matcher(rule);
while (m.find()) {
    idList.add(m.group());
}
for (String id : idList) {
    if (ObjectUtils.isNonEmpty(ruleMap.get(Integer.parseInt(id)))) {
        rule = rule.replaceFirst(id, ruleMap.get(Integer.parseInt(id)));
    }
}
System.out.println(rule);

我得到的输出是这样的:

A AND Test - Test - 12 OR Test Metadata 12 A AND 12 or Test Metadata 12 A

正如你所看到的,在第一次迭代中,id 12 被替换为了其对应的值,但在第二次出现 id 12 时,值从 Test - 12 替换为了 Test - Test - 12

所以,有谁可以帮我解决这个问题吗?

英文:

I need your help for one tricky problem.
I have one map like below

Map&lt;Integer, String&gt; ruleMap = new HashMap&lt;&gt;();
ruleMap.put(1, &quot;A&quot;);
ruleMap.put(12, &quot;Test - 12&quot;);
ruleMap.put(1012, &quot;Test Metadata 12 A&quot;);

and I have one rule in which I am separating ids and collecting them into a list. By iterating over the list, I am replacing its ids by its respective value from map.

code :

String rule = &quot;1 AND 12 OR 1012 AND 12 or 1012&quot;;

List &lt; String &gt; idList = new ArrayList &lt; &gt; ();

Pattern p = Pattern.compile(&quot;[0-9]+&quot;);
Matcher m = p.matcher(rule);
while (m.find()) {
    idList.add(m.group());
}
for (String id: idList) {
    if (ObjectUtils.isNonEmpty(ruleMap.get(Integer.parseInt(id)))) {
        rule = rule.replaceFirst(id, ruleMap.get(Integer.parseInt(id)));
    }
}
System.out.println(rule);

I am getting output like this -

A AND Test - Test - 12 OR Test Metadata 12 A AND 12 or Test Metadata 12 A

as you can see for the first iteration of id 12 replaced its respected value but on the second occurrence of the id 12 replaced the value Test - 12 to Test - Test - 12.

So can anyone help me with this?

答案1

得分: 4

你需要进行带有适当单词边界的正则表达式替换。我建议继续使用正则表达式迭代器(就像你之前已经在做的那样),但是使用模式 \b\d+\b 仅匹配完整的数字字符串。然后,在每次匹配时,根据数字是否存在,在规则映射中查找替换值。使用 Matcher#appendReplacement 在处理过程中逐步构建替换字符串。

Map<String, String> ruleMap = new HashMap<>();
ruleMap.put("1", "A");
ruleMap.put("12", "Test - 12");
ruleMap.put("1012", "Test Metadata 12 A");

String rule = "1 AND 12 OR 1012 AND 12 or 1012";

Pattern pattern = Pattern.compile("\\b\\d+\\b");
Matcher m = pattern.matcher(rule);
StringBuffer buffer = new StringBuffer();

while(m.find()) {
    if (ruleMap.containsKey(m.group(0))) {
        m.appendReplacement(buffer, ruleMap.get(m.group(0)));
    }
}

m.appendTail(buffer);

System.out.println(rule + "\n" + buffer.toString());

这将打印出:

1 AND 12 OR 1012 AND 12 or 1012
A AND Test - 12 OR Test Metadata 12 A AND Test - 12 or Test Metadata 12 A
英文:

You need to be doing regex replacement with proper word boundaries. I suggest using a regex iterator (as you were already doing), but use the pattern \b\d+\b to match only full number strings. Then, at each match, do a lookup in the rule map, if the number be present, to find a replacement value. Use Matcher#appendReplacement to build out the replacement string as you go along.

Map&lt;String, String&gt; ruleMap = new HashMap&lt;&gt;();
ruleMap.put(&quot;1&quot;, &quot;A&quot;);
ruleMap.put(&quot;12&quot;, &quot;Test - 12&quot;);
ruleMap.put(&quot;1012&quot;, &quot;Test Metadata 12 A&quot;);

String rule = &quot;1 AND 12 OR 1012 AND 12 or 1012&quot;;

Pattern pattern = Pattern.compile(&quot;\\b\\d+\\b&quot;);
Matcher m = pattern.matcher(rule);
StringBuffer buffer = new StringBuffer();
  
while(m.find()) {
    if (ruleMap.containsKey(m.group(0))) {
        m.appendReplacement(buffer, ruleMap.get(m.group(0)));
    }
}

m.appendTail(buffer);

System.out.println(rule + &quot;\n&quot; + buffer.toString());

This prints:

1 AND 12 OR 1012 AND 12 or 1012
A AND Test - 12 OR Test Metadata 12 A AND Test - 12 or Test Metadata 12 A

答案2

得分: 1

如果您恰好使用Java 9或更高版本,您还可以使用Matcher#replaceAll

Map<Integer, String> ruleMap = new HashMap<>();
ruleMap.put(1, "A");
ruleMap.put(12, "Test - 12");
ruleMap.put(1012, "Test Metadata 12 A");

String rule = "1 AND 12 OR 1012 AND 12 or 1012";

rule = Pattern.compile("\\b\\d+\\b")
        .matcher(rule)
        .replaceAll(m -> ruleMap.getOrDefault(
                Integer.parseInt(m.group()), m.group()));

System.out.println(rule);
英文:

If you happen to use Java 9 or higher you could also use Matcher#replaceAll:

Map&lt;Integer, String&gt; ruleMap = new HashMap&lt;&gt;();
ruleMap.put(1, &quot;A&quot;);
ruleMap.put(12, &quot;Test - 12&quot;);
ruleMap.put(1012, &quot;Test Metadata 12 A&quot;);

String rule = &quot;1 AND 12 OR 1012 AND 12 or 1012&quot;;

rule = Pattern.compile(&quot;\\b\\d+\\b&quot;)
        .matcher(rule)
        .replaceAll(m -&gt; ruleMap.getOrDefault(
                Integer.parseInt(m.group()), m.group()));

System.out.println(rule);

huangapple
  • 本文由 发表于 2020年10月13日 18:47:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/64333751.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定