3

Example:

input = "10N10N";
input = input.replaceAll("1|N", "N|1"); // syntax not correct

expected output: N01N01

What I'm asking is for a single-lined iterator that replaces all "1" with "N" and all "N" with "1".

1
  • Regex doesn't work like that in general : an alternation in a replacement pattern makes no sense. You're writing characters in that pattern, and the only meta-characters generally allowed are back-references which make you able to refer to parts or integrity of the matched string. Commented Feb 3, 2018 at 17:31

3 Answers 3

5

Since Java 9 Matcher class contains replaceAll​(Function<MatchResult,String> replacer) where you can specify dynamically what should be used as replacement based on current match. So your code may look like:

Map<String, String> replacementsMap = Map.ofEntries(
        Map.entry("1", "N"),
        Map.entry("N", "1")
);

String input = "10N10N";
Pattern p = Pattern.compile("1|N");
Matcher m = p.matcher(input);
String replaced = m.replaceAll(match -> replacementsMap.get(match.group()));
System.out.println(replaced);

Output: N01N01.


In pre Java 9 you can use Matcher#appendReplacement and Matcher#appendTail instead of replaceAll like

//create Pattern p, Matcher m and replacement map
StringBuffer sb = new StringBuffer();
while(m.find()){
    m.appendReplacement(sb, replacementsMap.get(m.group()));
}
m.appendTail(sb);
String replaced = sb.toString();

If you are willing to use external libraries then Apache Commons - Lang include StringUtils class with replaceEach(String text, String[] searchList, String[] replacementList) method. You can use it like:

String input = "10N10N";
String replaced = StringUtils.replaceEach(input, new String[] {"1","N"}, new String[] {"N","1"});
System.out.println(replaced);//N01N01
Sign up to request clarification or add additional context in comments.

1 Comment

oh, that looks nice!
3

I'd advise you to prefer not going the regex way. Instead, why not go this way:

  • Replace all 1 with _ (OR any not-present char in the input string), then replace N by 1, and further replace _ by N.

This can be easily done by multiple replaces, all within a single line.

Comments

3

Try to use :

input = input.replace("1", "-")//replace all 1 by - 
        .replace("N", "1")     //replace all N by 1
        .replace("-", "N");    //replace all - by N

More secure solution, if you are using Java 8 you can use :

String result = input.chars()
        .map(x -> x == 'N' ? '1' : x == '1' ? 'N' : x)
        .collect(StringBuilder::new,
                StringBuilder::appendCodePoint,
                StringBuilder::append
        ).toString();

Output

N01N01

2 Comments

Could you explain what you mean by “more secure solution?”
@Joey Grant The first solution need a 3rd character, I used - but what if the input can have a hyphen before? for example 10N-10N in this case the 3rd replace will replace also this hyphen, but the second solution don't need that 3rd character, It loop over all character and check if it is equal to N then return 1 else if N return it with 1 and in the end collect all the result this is what is mean by "more secure solution" hope you get it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.