다음 교체를 위해 스캔을 다시 시작하고 가장 짧은 입력을 먼저 스캔하는 것이 문제입니다. a
가 이미 abc
에 대한 스캔하기 전에, 다른 무언가로 대체 되었기 때문에 스캔하여
는 a
에 대한 abc
전에, abc
과 일치하지 않습니다. 길이가 가장 긴 부분을 스캔 할 부분을 commented by rgettman으로 정렬합니다.
각 입력에 대한 검색을 다시 시작하면 대체 값의 내용을 바꿀 수 있습니다. 예 : 당신이 a
전에 b
를 검색 할 경우, b
은 false
로 대체됩니다,하지만 false
의 a
은 ftruelse
로 대체하기 시작 b
결과, true
로 대체됩니다.
두 번째 문제점을 수정하고 성능을 향상 시키려면 입력을 한 번만 스캔해야합니다.
입력을 한 번 스캔하고 여러 텍스트 중 하나를 스캔하는 가장 쉬운 방법은 abc|a|b
과 같은 정규식을 사용하는 것입니다. 즉 가장 긴 키를 먼저 |
으로 구분 한 키를 나열하는 것입니다.
대체 매핑이 무엇이든 할 수 있다고 가정하면 Map
에서 동적으로 정규식을 작성해야합니다. 특수 문자는 정규식 특수 문자로 취급되지 않으므로 키와 값을 모두 인용해야한다는 점을 기억해야합니다. 예 일치하는 모든 문자 .
.여기
모든 것을 사용 정규식 여분의 반복 수행 (자바 8) 방법 :
public static String replace(String input, Map<String, String> replacementValues) {
String regex = replacementValues.keySet().stream()
.sorted(Comparator.comparingInt(String::length).reversed()
.thenComparing(Function.identity()))
.map(Pattern::quote)
.collect(Collectors.joining("|"));
StringBuffer buf = new StringBuffer(input.length() + 16);
Matcher m = Pattern.compile(regex).matcher(input);
while (m.find())
m.appendReplacement(buf, Matcher.quoteReplacement(replacementValues.get(m.group())));
return m.appendTail(buf).toString();
}
테스트
Map<String, String> map = new HashMap<>();
map.put("a", "true");
map.put("b", "false");
map.put("abc", "true");
System.out.println(replace("abc|a&b", map));
출력
true|true&false
스캔이 단어가 아닌 문자열과 일치하는 정규 표현식 컴파일 변경해야하는 경우 : 길이로 감소하는 열쇠는, 그 순서대로 적용
Pattern.compile("\\b(?:" + regex + ")\\b")
정렬. – rgettman
당신은 세 가지 대답을 가지고 있습니다. 모두 문제를 해결하지만, 당신은 그 중 하나를 upvote 또는 accept하지 않았습니다! 나는 이전에 내 대답을 받아들이고 댓글을 달았 기 때문에 (당신이 당신의 의견을 삭제 했음에도) 당신이 그들을 본 것을 압니다. 왜? 사람들은 당신을 돕기 위해 진정한 노력을했습니다. –