Comforse
Comforse

Reputation: 2066

Java: replace a set of characters with other different characters

I am supposed to make a custom decorator so I can replace both in an input from console and from a file:

  1. A set of chars with a specific character (e.g. char[] x = {'a', 'b'} with char y = '*', so both a and b become *
  2. A set of chars with another set of paired chars (e.g. char[] x = {'a', 'b'} with char[] y = {'c', 'd'}, so a becomes c and b becomes d

What would be the best approach for it? I made the first one with a regular expression ( String replaceAll = s.replaceAll("(a|b)", String.valueOf(replacement)); ), but this wouldn't work for the second case. Is there a way to make the second case in one regex? Should I do a HashMap ?

Upvotes: 1

Views: 3412

Answers (4)

Pshemo
Pshemo

Reputation: 124225

It would be easier to first create some kind of mapping between replaced character and its replacement. I mean something like

Map<String, String> map = new HashMap<>();
map.put("a", "c");
map.put("b", "d");

then you can use appendReplacement and appendTail from Matcher class to replace matched character. Deciding on how to get replaced character can be done like map.get(matchedCharacter).

Simple Demo

Map<String, String> map = new HashMap<>();
map.put("a", "c");
map.put("b", "d");

String demo = "abcdef";

Pattern p = Pattern.compile("[ab]");
Matcher m = p.matcher(demo);

StringBuffer sb = new StringBuffer();
while (m.find()){
    m.appendReplacement(sb, map.get(m.group()));
}
m.appendTail(sb);
String replaced = sb.toString();

System.out.println(replaced);

Output: cdcdef


UPDATE for Java 9 and above

In below template we usually change only one thing, decision about what to use as replacement of founded match.

StringBuffer sb = new StringBuffer();
while (m.find()){
    m.appendReplacement(sb, /* decision about replacement*/ );
    //                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
}
m.appendTail(sb);
String replaced = sb.toString();

So since rest of that logic is repeated, this template was wrapped as String replaceAll​(Function<MatchResult,String> replacer) which require from us to provide logic of obtaining replacement for founded match. So above code can be reduced to:

Map<String, String> map = new HashMap<>();
map.put("a", "c");
map.put("b", "d");

String demo = "abcdef";

Pattern p = Pattern.compile("[ab]");
Matcher m = p.matcher(demo);

String replaced = m.replaceAll(match -> map.get(match.group()));
System.out.println(replaced);

Upvotes: 2

Paul Vargas
Paul Vargas

Reputation: 42030

There is a more faster way:

public static void main(String[] args) {
    String target      = "ab";
    String replacement = "**";

    char[] array = "abcde".toCharArray();
    for (int i = 0; i < array.length; i++) {
        int index = target.indexOf(array[i]);
        if (index != -1) {
            array[i] = replacement.charAt(index);
        }
    }

    System.out.println(array);
}

Upvotes: 1

Matej Špil&#225;r
Matej Špil&#225;r

Reputation: 2687

Here you have, this work 100% right for any example ....

public static void main(String[] args) {
        String test = "My name is Baba";

        Character[] x = { 'a', 'b' };

        StringBuilder sb = new StringBuilder();
        sb.append("(");
        for (int i = 0; i < x.length; i++) {
            if (i == (x.length - 1)) {
                sb.append(x[i] + ")");
            } else {
                sb.append(x[i] + "|");
            }
        }

        System.out.println(sb.toString());

        Character y = 'c';
        Character[] y1 = { 'd', 'e' };

        if (y.getClass().isArray()) {
            for (int i = 0; i < y1.length; i++) {
                test = test.replaceAll(x[i].toString(), y1[i].toString());
            }
        } else {
            test = test.replaceAll(sb.toString(), String.valueOf(y.toString()));
        }

        System.out.println(test);
    }

Upvotes: 1

zx81
zx81

Reputation: 41838

DjMike,

For the second one, what would be helpful during the replacement is to call a method that you infuse with the logic to replace different characters with different strings.

PHP has a great facility that does just this called preg_replace_callback(). The linked answer is to a question about the Java equivalent of preg_replace_callback()

Upvotes: 1

Related Questions