java字符串替换字符

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

java String replace characters

问题

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

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

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

代码:

  1. String rule = "1 AND 12 OR 1012 AND 12 or 1012";
  2. List<String> idList = new ArrayList<>();
  3. Pattern p = Pattern.compile("[0-9]+");
  4. Matcher m = p.matcher(rule);
  5. while (m.find()) {
  6. idList.add(m.group());
  7. }
  8. for (String id : idList) {
  9. if (ObjectUtils.isNonEmpty(ruleMap.get(Integer.parseInt(id)))) {
  10. rule = rule.replaceFirst(id, ruleMap.get(Integer.parseInt(id)));
  11. }
  12. }
  13. System.out.println(rule);

我得到的输出是这样的:

  1. 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

  1. Map&lt;Integer, String&gt; ruleMap = new HashMap&lt;&gt;();
  2. ruleMap.put(1, &quot;A&quot;);
  3. ruleMap.put(12, &quot;Test - 12&quot;);
  4. 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 :

  1. String rule = &quot;1 AND 12 OR 1012 AND 12 or 1012&quot;;
  2. List &lt; String &gt; idList = new ArrayList &lt; &gt; ();
  3. Pattern p = Pattern.compile(&quot;[0-9]+&quot;);
  4. Matcher m = p.matcher(rule);
  5. while (m.find()) {
  6. idList.add(m.group());
  7. }
  8. for (String id: idList) {
  9. if (ObjectUtils.isNonEmpty(ruleMap.get(Integer.parseInt(id)))) {
  10. rule = rule.replaceFirst(id, ruleMap.get(Integer.parseInt(id)));
  11. }
  12. }
  13. System.out.println(rule);

I am getting output like this -

  1. 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 在处理过程中逐步构建替换字符串。

  1. Map<String, String> ruleMap = new HashMap<>();
  2. ruleMap.put("1", "A");
  3. ruleMap.put("12", "Test - 12");
  4. ruleMap.put("1012", "Test Metadata 12 A");
  5. String rule = "1 AND 12 OR 1012 AND 12 or 1012";
  6. Pattern pattern = Pattern.compile("\\b\\d+\\b");
  7. Matcher m = pattern.matcher(rule);
  8. StringBuffer buffer = new StringBuffer();
  9. while(m.find()) {
  10. if (ruleMap.containsKey(m.group(0))) {
  11. m.appendReplacement(buffer, ruleMap.get(m.group(0)));
  12. }
  13. }
  14. m.appendTail(buffer);
  15. System.out.println(rule + "\n" + buffer.toString());

这将打印出:

  1. 1 AND 12 OR 1012 AND 12 or 1012
  2. 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.

  1. Map&lt;String, String&gt; ruleMap = new HashMap&lt;&gt;();
  2. ruleMap.put(&quot;1&quot;, &quot;A&quot;);
  3. ruleMap.put(&quot;12&quot;, &quot;Test - 12&quot;);
  4. ruleMap.put(&quot;1012&quot;, &quot;Test Metadata 12 A&quot;);
  5. String rule = &quot;1 AND 12 OR 1012 AND 12 or 1012&quot;;
  6. Pattern pattern = Pattern.compile(&quot;\\b\\d+\\b&quot;);
  7. Matcher m = pattern.matcher(rule);
  8. StringBuffer buffer = new StringBuffer();
  9. while(m.find()) {
  10. if (ruleMap.containsKey(m.group(0))) {
  11. m.appendReplacement(buffer, ruleMap.get(m.group(0)));
  12. }
  13. }
  14. m.appendTail(buffer);
  15. System.out.println(rule + &quot;\n&quot; + buffer.toString());

This prints:

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

答案2

得分: 1

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

  1. Map<Integer, String> ruleMap = new HashMap<>();
  2. ruleMap.put(1, "A");
  3. ruleMap.put(12, "Test - 12");
  4. ruleMap.put(1012, "Test Metadata 12 A");
  5. String rule = "1 AND 12 OR 1012 AND 12 or 1012";
  6. rule = Pattern.compile("\\b\\d+\\b")
  7. .matcher(rule)
  8. .replaceAll(m -> ruleMap.getOrDefault(
  9. Integer.parseInt(m.group()), m.group()));
  10. System.out.println(rule);
英文:

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

  1. Map&lt;Integer, String&gt; ruleMap = new HashMap&lt;&gt;();
  2. ruleMap.put(1, &quot;A&quot;);
  3. ruleMap.put(12, &quot;Test - 12&quot;);
  4. ruleMap.put(1012, &quot;Test Metadata 12 A&quot;);
  5. String rule = &quot;1 AND 12 OR 1012 AND 12 or 1012&quot;;
  6. rule = Pattern.compile(&quot;\\b\\d+\\b&quot;)
  7. .matcher(rule)
  8. .replaceAll(m -&gt; ruleMap.getOrDefault(
  9. Integer.parseInt(m.group()), m.group()));
  10. 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:

确定