0

I want to modify two characters in the string, for example change each 'i' into 'e', and each 'e' into 'i' so text like "This is a test" will become "Thes es a tist".

I've made a solution that works, but it is boring and inelegant:

String input = "This is a test";
char a = 'i';
char b = 'e';

char[] chars = input.toCharArray();
for(int i = 0; i < chars.length; i++) {
    if(chars[i] == a) {
        chars[i] = b;
    }else if(chars[i] == b) {
        chars[i] = a;
    }
}

input = new String(chars);

How can this be accomplished with regex?

1
  • @feelingunwelcome that duplicate is about swapping two characters (changing their positions), while this is about changing characters with different ones while replacement characters doesn't even need to exist in original string at all. Commented Sep 22, 2018 at 11:50

2 Answers 2

5

Since Java 9 we can use Matcher#replaceAll(Function<MatchResult,String>). So you can create regex which will search for either i or e, and when it finds it let function pick replacement based on found value (like from map)

Demo

Map<String, String> replacements = Map.ofEntries(
        Map.entry("i", "e"), 
        Map.entry("e", "i")
);
String replaced = Pattern.compile("[ie]")
                         .matcher(yourString)
                         .replaceAll((match) -> replacements.get(match.group()));

But to be honest your solution doesn't look bad, especially if it is used for searching for single characters.

Sign up to request clarification or add additional context in comments.

2 Comments

That's a really cool solution, but I'm on Java 8, unfortunately.
I would like to remind that Java 11 will be released in this month. Anyway using map to pick replacement can be also applied in your own solution instead of ifs.
2

A less elegant solution than Pschemo's but usable since Java 8:

static String swap(String source, String a, String b) {
    // TODO null/empty checks and length checks on a/b
    return Arrays
        // streams single characters as strings
        .stream(source.split(""))
        // maps characters to their replacement if applicable
        .map(s -> {
            if (s.equals(a)) {
                return b;
            }
            else if (s.equals(b)) {
                return a;
            }
            else {
                return s;
            }
        })
        // rejoins as single string
        .collect(Collectors.joining());
}

Invoked on "This is a test", it returns:

Thes es a tist

Note

As mentioned by others, your solution is fine as is for single characters.

1 Comment

We can also use instead of ifs Map<String, String> replacements and map(s->replacements.getOrDefault(s,s)) to let s be returned in case when replacement doesn't have s key.

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.