I am going through the CodingBat exercises for Java. I have just completed this one:
Given two strings,
base
andremove
, return a version of thebase
string where all instances of theremove
string have been removed (not case sensitive). You may assume that the remove string is length 1 or more. Remove only non-overlapping instances, so withxxx
removingxx
leavesx
.
I wanted to try using a StringBuilder
to solve this because I have not done so before. Here is my code:
public String withoutString(String base, String remove){
String removeLo = remove.toLowerCase();
String removeHi = remove.toUpperCase();
int rL = remove.length();
StringBuilder s = new StringBuilder(base);
for (int i = 0; i < s.length(); i++) {
int j = s.indexOf(remove, i);
if (j < 0) {
break;
} else {
s.delete(j, j + rL);
}
}
for (int i = 0; i < s.length(); i++) {
int j = s.indexOf(removeLo, i);
if (j < 0) {
break;
} else {
s.delete(j, j + rL);
}
}
for (int i = 0; i < s.length(); i++) {
int j = s.indexOf(removeHi, i);
if (j < 0) {
break;
} else {
s.delete(j, j + rL);
}
}
return s.toString();
}
The code repeats the for loop 3 times in order to search for the unaltered, lower case, and upper case versions of remove
. My questions are:
- Is it possible to reduce this down to one
for
loop, and is that practical (with good readability)? - The test strings involve digits. Is it problematic to be 'converting' these to lower and/or upper cases? Should I deal with those before testing the alphabetic strings?
The following test cases are the ones that require all three
for
loops:withoutString("xxx", "x") withoutString("1111", "1") withoutString("MkjtMkx", "Mk") withoutString("Hi HoHo", "Ho")
The rest of the tests work without the first
for
loop (unalteredremove
). The second two make sense, because theremove
string uses upper and lower case, but the first two don't follow this. I have used the debugger in Eclipse but I still can't figure this out. Can you please explain?
Matcher
class makes sure that only non-overlapping Strings are matched. It all comes down to one line:return Pattern.compile(remove, Pattern.CASE_INSENSITIVE).matcher(base).replaceAll("");
. \$\endgroup\$