1

I have a question about replacing words. I have some strings, each of which looks like this:

String string = "today is a (happy) day, I would like to (explore) more about Java."

I need to replace the words that have parentheses. I want to replace "(happy)" with "good", and "(explore)" with "learn".

I have some ideas, but I don't know how.

for (int i = 0; i <= string.length(), i++) {
  for (int j = 0; j <= string.length(), j++
    if ((string.charAt(i)== '(') && (string.charAt(j) == ')')) {
      String w1 = line.substring(i+1,j);
      string.replace(w1, w2)
    }
  }
}

My problem is that I can only replace one word with one new word...

I am thinking of using a scanner to prompt me to give a new word and then replace it, how can I do this?

dda
  • 6,030
  • 2
  • 25
  • 34
Sally
  • 87
  • 2
  • 10
  • 1
    `string = string.replaceAll("(happy)", "good").replaceAll("(explore)", "learn");` – Nir Alfasi Apr 08 '17 at 03:56
  • but the thing is I have many strings with (word)... I can't use this for all of them – Sally Apr 08 '17 at 03:58
  • Are you want that to be dynamic of any words use regex or just this case, And if just this case @alfasin answer is good – Fady Saad Apr 08 '17 at 03:58
  • 3
    Strings are immutable in Java, so the [`String.replace()`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replace-java.lang.CharSequence-java.lang.CharSequence-) method **returns the new value**. It doesn't update the existing value, because it can't. Use `string = string.replace(w1, w2)`. – Andreas Apr 08 '17 at 03:58
  • Your code is wrong, J should start its scan at I+1, not 0... – Guillaume F. Apr 08 '17 at 03:59
  • How do you keep a track of what `w2` is for a given `w1`? – VHS Apr 08 '17 at 04:01
  • @Vicky your comment is not clear... if you know in advance that `w1` represents a word to be replaced (including the brackets) and `w2` represents the word that replaces `w1` you can do the same as I suggested with `w1` and `w2`: `string = string.replace(w1, w2);` – Nir Alfasi Apr 08 '17 at 04:01
  • 1
    No need to use the nested loops. Better use one loop and store the index when you find opening parenthesis and also for close parenthesis and replace it with the word. Continue the same loop and store next index. As you are replacing the words in same string it changes the length of string you need to maintain copy of string and perform loop and replace on different, – Sumit Gulati Apr 08 '17 at 04:02
  • 1
    @alfasin The code isn't good. You probably meant to use [`replace("(happy)", "good")`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replace-java.lang.CharSequence-java.lang.CharSequence-), because [`replaceAll()`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replaceAll-java.lang.String-java.lang.String-) uses a *regular expression*, where `()` has special meaning, so that code will not replace the literal text `(happy)`, only the text `happy`, leaving the `()` in place. – Andreas Apr 08 '17 at 04:02
  • 1
    Possible duplicate of [How to replace multiple substring of a string at one time?](http://stackoverflow.com/q/38649267/5221149), or [Java Regex String#replaceAll Alternative](http://stackoverflow.com/q/41407648/5221149) – Andreas Apr 08 '17 at 04:04
  • @Andreas you're right my bad- should have used `replace` – Nir Alfasi Apr 08 '17 at 04:05

6 Answers6

2

The appendReplacement and appendTail methods of Matcher are designed for this purpose. You can use a regex to scan for your pattern--a pair of parentheses with a word in the middle--then do whatever you need to do to determine the string to replace it with. See the javadoc.

An example, based on the example in the javadoc. I'm assuming you have two methods, replacement(word) that tells what you want to replace the word with (so that replacement("happy") will equal "good" in your example), and hasReplacement(word) that tells whether the word has a replacement or not.

Pattern p = Pattern.compile("\\((.*?)\\)");
Matcher m = p.matcher(source);
StringBuffer sb = new StringBuffer();
while (m.find()) {
    String word = m.group(1);
    String newWord = hasReplacement(word) ? replacement(word) : m.group(0);
    m.appendReplacement(sb, newWord); // appends the replacement, plus any not-yet-used text that comes before the match
}
m.appendTail(sb); // appends any text left over after the last match
String result = sb.toString();
ajb
  • 31,309
  • 3
  • 58
  • 84
  • 1
    Don't call `appendReplacement()` unless you're replacing, i.e. `if (hasReplacement(word)) { m.appendReplacement(sb, replacement(word)); }`. The "append position" described in the javadoc is independent of the `find()` method, so you don't have to call `appendReplacement()` in a `find()` loop. – Andreas Apr 08 '17 at 04:33
  • Performance can be improved by having the regex pattern match the target keywords, as done in [this answer](http://stackoverflow.com/a/41407783/5221149). – Andreas Apr 08 '17 at 04:36
1

Use below code for replacing the string.

String string = "today is a (happy) day, I would like to (explore) more about Java.";
string = string.replaceAll("\\(happy\\)", "good");
string = string.replaceAll("\\(explore\\)", "learn");
System.out.println(string);`
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
nick
  • 44
  • 4
0

What you can do is run a loop from 0 to length-1 and if loop encounters a ( then assign its index to a temp1 variable. Now go on further as long as you encounter ).Assign its index to temp2 .Now you can replace that substring using string.replace(string.substring(temp1+1,temp2),"Your desired string")).

Bharat
  • 1,044
  • 15
  • 34
0

No need to use the nested loops. Better use one loop and store the index when you find opening parenthesis and also for close parenthesis and replace it with the word. Continue the same loop and store next index. As you are replacing the words in same string it changes the length of string you need to maintain copy of string and perform loop and replace on different,

Sumit Gulati
  • 665
  • 4
  • 14
0

Do not use nested for loop. Search for occurrences of ( and ). Get the substring between these two characters and then replace it with the user entered value. Do it till there are not more ( and ) combinations left.

import java.util.Scanner;

public class ReplaceWords {

    public static String replaceWords(String s){
        while(s.contains(""+"(") && s.contains(""+")")){
            Scanner keyboard = new Scanner(System.in);
            String toBeReplaced = s.substring(s.indexOf("("), s.indexOf(")")+1);
            System.out.println("Enter the word with which you want to replace "+toBeReplaced+" : ");
            String replaceWith = keyboard.nextLine();
            s = s.replace(toBeReplaced, replaceWith);
        }
        return s;
    }

    public static void main(String[] args) {
        String myString ="today is a (happy) day, I would like to (explore) more about Java.";
        myString = replaceWords(myString);
        System.out.println(myString);
    }
}
0

This snippet works for me, just load the HashMap up with replacements and iterate through:

import java.util.*;

public class Test
{
    public static void main(String[] args) {
        String string = "today is a (happy) day, I would like to (explore) more about Java.";
        HashMap<String, String> hm = new HashMap<String, String>();
        hm.put("\\(happy\\)", "good");
        hm.put("\\(explore\\)", "learn");

        for (Map.Entry<String, String> entry : hm.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            string = string.replaceAll(key, value);
        }
        System.out.println(string);
    }
}

Remember, replaceAll takes a regex, so you want it to display "\(word\)", which means the slashes themselves must be escaped.

Darkstarone
  • 4,590
  • 8
  • 37
  • 74