alanbuchanan
alanbuchanan

Reputation: 4173

Unexpected output for looping through a string and using str.replace

I am going through the CodingBat exercises for Java. I have got up to this problem which asks:

Given a string, return a version where all the "x" have been removed. Except an "x" at the very start or end should not be removed.

I wanted to solve this by checking each character from the second up to the penultimate of the string. If the character is x, replace it with an empty character. Here is my code:

public String stringX(String str) {
    String newStr = "";
    for (int i = 1; i < str.length()-1; i++) {
        if (str.indexOf('x') == i) {
            newStr += str.replace('x', '\u0000');
        }
    }
    return newStr;
}

The result of this is that it doesn't seem to return any of the string passed in, if the string begins with x:

System.out.println(test.stringX("xxHxix"));

returns (blank)

System.out.println(test.stringX("abxxxcd"));

returns abcd

System.out.println(test.stringX("xabxxxcdx"));

returns (blank)

I really can't figure out what's going on but I want to be able to understand it before just looking at the answer.

Is it problematic to concatenate a char into a string? Should I use substring instead?

Upvotes: 1

Views: 77

Answers (3)

Code Whisperer
Code Whisperer

Reputation: 1041

if (str.indexOf('x') == i) {
            newStr += str.replace('x', '\u0000');
        }

This will always return the same result, the first occurrence of char x. If the first occurrence of x != i it will never go into the if statement.

This should work:

public String stringX(String str) {
    for (int i = 1; i < str.length() - 1; i++) {
        if (str.charAt(i) == 'x') {
            str.deleteCharAt(i);
        }
    }
    return str;
}

EDIT: removed the unnecessary variable declaration.

Upvotes: 3

Avinash Raj
Avinash Raj

Reputation: 174706

You could use string.replaceAll function. The below regex will remove all the x except the ones which are at the start or at the end.

System.out.println("xxHxix".replaceAll("(^x|x$)|x", "$1"));
System.out.println("xabxxxcdx".replaceAll("(^x|x$)|x", "$1"));

Output:

xHix
xabcdx

DEMO

  • ^x would match the x which was at the start of a line. ^ anchor asserts that we are at the start.
  • x$ would match the x which was at the end.
  • (..) called capturing group usually used to capture characters. So (^x|x$) captures the starting x or the x at the end.
  • |x OR match all the x from the remaining string. | called regex alternation operator. So (^x|x$)|x will match all the x which was at the middle and captures all the x which was at the start or at the end.
  • Replacing all the matched chars with the chars inside group index 1 will return only the x's (which are at the start or at the end)

If you want to do a case-insensitive match then add (?i) modifier at the start like

"(?i)(^x|x$)|x"

Upvotes: 3

Murat Karag&#246;z
Murat Karag&#246;z

Reputation: 37594

You are creating a newStr and replace every x on it. Because str.replace('x', '\u0000'); does so.

What you want to do is to use the method charAt(x) to check specific characters and create a new string with it or remove the matched indexes on the current string.

Check out the Java Doc for String

Upvotes: 1

Related Questions