views:

438

answers:

5

I currently have a string which contains the characters A, B and C for example the string looks like

"A some other random stuff B C"

the other random stuff doesn't contain A, B or C I want to replace the A, B & C with 'A', 'B' and 'C' respectively what's the best way to do that currently I'm doing:

String.replace("A", "'A'").replace("B", "'B'").replace("C", "'C'")
+9  A: 

Use a regular expression:

String input = "A some other random stuff B C";
String output = input.replaceAll("[ABC]", "'$0'");

Output:

'A' some other random stuff 'B' 'C'
cletus
it just return "'1' some other random stuff '1' '1'";
Aly
Got my languages mixed up :) It's $N to refer to args in Java not \N like I originally had.
cletus
+12  A: 

cletus' answer works fine if A, B and C are those exact single characters, but not if they could be longer strings and you just called them A, B and C for example purposes. If they are longer strings you need to do:

String input = "FOO some other random stuff BAR BAZ";
String output = input.replaceAll("FOO|BAR|BAZ", "'$0'");

You will also need to escape any special characters in FOO, BAR and BAZ so that they are not interpreted as special regular expression symbols.

Mark Byers
u need to make it $0 not \\1
Aly
$1 would work in this case too because the whole match is being captured in parentheses.
cletus
Actually the parentheses are not required - I'll update the post.
Mark Byers
+1  A: 

I think regex is not really suitable if those are fairly complex strings.

Consider just wrapping it in your own utility method taking arrays or lists as arguments.

public static String replace(String string, String[] toFind, String[] toReplace) {
    if (toFind.length != toReplace.length) {
        throw new IllegalArgumentException("Arrays must be of the same length.");
    }
    for (int i = 0; i < toFind.length; i++) {
        string = string.replace(toFind[i], toReplace[i]);
    }
    return string;
}

Maybe there's already one in the Apache Commons or Google Code. Give it a look if you prefer 3rd party API's above homegrown stuff.

Edit: why downvoting a technically correct but a in your opinion not preferred answer? Just don't upvote.

BalusC
Good idea, but replace only takes "char", he wanted to replace a "char" with a String ('A'). Besides, don't loop on string modifications--performance will be abysmal (bordering on bad code). If you want to iterate over it like you did, use some string building mechanism (say, StringBuilder perhaps?)
Bill K
And by the way, I'd never suggest optimizing for performance except in a few really blatant cases--Creating and destroying objects in a loop unnecessarily is one of them.
Bill K
String has two replace methods. One taking char and other taking CharSequence (since Java 1.5 several years ago). Guess what String implements? Link: http://java.sun.com/javase/6/docs/api/java/lang/String.html#replace%28java.lang.CharSequence,%20java.lang.CharSequence%29
BalusC
I don't get your performance concern, so I won't go in it.
BalusC
You're right--I missed the second replace (I even checked!). Still, he is trying to find one char (length 1) and replace it with 3, your code would just throw an exception. The performance comment is referring to the fact that each .replace call actually allocates a new string. Each time you call it, you throw away the old one and allocate a new one (string = string). This is okay in a one-off scenario, but seriously--avoid it in loops. It's one of the few things that actually will trash your performance in a large loop.
Bill K
I don't see why it would throw exception if you replace "A" by "'A'". Performance concern is understood, but hey, it was just a kickoff example. We're here not at Sun HQ or so.
BalusC
This just checks if the arrays are of the same length? I really don't see why they should be of different lengths. You just need to call it as for example: `replace(string, new String[] {"A", "B", "C"}, new String[] {"'A'", "'B'", "'C'"});` .. Ah, while typing this I see the repeat in the singlequotes. OK, understood, but that was really not the intent.
BalusC
I was wrong, sorry. Didn't see that was how you intended to use it.
Bill K
No problem, can even happen to Einstein.
BalusC
BTW: Your answer isn't as bad at performance as I thought either--although I still stay away from allocating in loops, it's no worse than chaining them (in the style of the original questioner). StringBuilder would require iterating over the entire string since it has no replace/replaceAll functionality, so aside from the RegularExpression answer (which I'm skittish about as well), this is as good as you're likely to get.
Bill K
By coincidence, I checked the source of `replace(CharSequence, CharSequence)` and it **do** actually use `replaceAll` under the hoods as you demonstrated, but then with an extra flag `Pattern.LITERAL` which should likely decrease overhead.
BalusC
+1  A: 

The other peoples answers are better, but under the assumption you are trying to learn, I wanted to point out the problems with your original code.

Here would be a "Fixed" version of what you are trying to do (Using your style, which was close) and the things you need to do to make it work:

public String quoteLetters(String s)
{
    return s.replace("A", "'A'").replace("B", "'B'").replace("C", "'C'");
}

Here are the problems you had:

  • Replace is a method, not a static function, so you have to call it on an instance of String, not String itself.
  • Replace returns an instance of the new string, it cannot modify the original string. In my code, I'm "Returning" the new string, s remains unmodified.
  • If this is homework, you should have tagged it as such.
  • Don't chain them like I did--the other answers are better because mine will actually create 3 new strings and then immediately destroy them.
Bill K
Too much overhead, just use replace(). Or install JDK >= 1.5.
BalusC
Absolutely--I even said so. I was just telling him what he did wrong assuming he was trying to learn.
Bill K
And good advice about replace() I've been living in Java 1.1 land WAY too long.
Bill K
+3  A: 

Have a look at StringUtils from Apache Commons Lang and its various replace methods.

Pascal Thivent
up vote... I always first take a look in apache *Utils first!!
Castanho
I dislike Apache Commons since they've seemed to be mostly lost in the pre-generics era. I mean come on, Java 5 which introduced generics reached its EOL couple of weeks ago.
Esko
@Esko Not false. Not sure this a problem when manipulating `String` though :)
Pascal Thivent