英文:
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<Integer, String> ruleMap = new HashMap<>();
ruleMap.put(1, "A");
ruleMap.put(12, "Test - 12");
ruleMap.put(1012, "Test Metadata 12 A");
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 = "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);
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 1
2 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<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());
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<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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论