2
\$\begingroup\$

I'm trying to reduce consecutive elements of array to one, but not for all values like:

{3,0,0,0,3,3,3,0,0,0} => {3,0,3,0}

but for specific one, in my example 0:

{3,0,0,0,3,3,3,0,0,0} => {3,0,3,3,3,0}

so only zeros (the threes are intact) are reduced.

I have Java String working code I wrote:

public static String removeConsecutive(String str, char remove) {
    char[] chars = str.toCharArray();

    int current = 0;
    int result  = current;
    while (current < chars.length) {
        if (chars[current] == remove) {
            // keep the first occurrence
            chars[result++] = chars[current++];

            // ignore the others
            while (current < chars.length && chars[current] == remove) {
                ++current;
            }
        } else {            
            chars[result++] = chars[current++];
        }
    }

    return new String(chars, 0, result);
}

and it does the trick:

public static void main(String[] args) {
    System.out.println(removeConsecutive("000300300030303330000", '0'));
}

outputs: 0303030303330

Can anyone suggest any improvements, since it think the code is not perfect. It's doesn't have to be String in use, but with any other array.

\$\endgroup\$

6 Answers 6

1
\$\begingroup\$

Here's the same answer that I gave on you Stack Overflow:

Think this is clearer, and does the job:

public static String removeConsecutive(String str, char remove) {
    StringBuilder sb = new StringBuilder();
    for(char c : str.toCharArray()) {
        int length = sb.length();
        if(c != remove || length == 0 || sb.charAt(length - 1) != c) {
            sb.append(c);
        }
    }
    return sb.toString();
}
\$\endgroup\$
5
\$\begingroup\$

You can have the same output with regex , using Arrays.toString(char[]):

System.out.println("000300300030303330000".replaceAll("[0]+", "0"));

or, with a parameter :

char charToRemove = '0' ;
System.out.println("000300300030303330000".replaceAll("[" + charToRemove + "]{1,}", charToRemove + ""));

or change charToRemove + "" in Character.toString(charToRemove) more academic.

\$\endgroup\$
6
  • \$\begingroup\$ {1,} is just + ;) \$\endgroup\$
    – fge
    Jun 13, 2013 at 9:35
  • \$\begingroup\$ @fge changed, both works \$\endgroup\$
    – cl-r
    Jun 13, 2013 at 9:38
  • \$\begingroup\$ Hi @cl-r, tnx for your answer, but I'm trying to avoid regex and replace / replaceAll methods when removing only one char, since it inefficient. \$\endgroup\$
    – robosoul
    Jun 13, 2013 at 10:20
  • 1
    \$\begingroup\$ @robosoul It is more efficient to declare static field Pattern.compile(regex); and use them as needed ; powerful with complex matches. It would be intresting to compare regex and StringBuilder response time with many arrays to test. \$\endgroup\$
    – cl-r
    Jun 13, 2013 at 10:33
  • \$\begingroup\$ Nit: When matching a single character 0+ does the same job as [0]+. \$\endgroup\$
    – l0b0
    Jun 13, 2013 at 12:23
3
\$\begingroup\$

Another apporach to the removeConsecutive method, using a StringBuilder and String.charAt():

public static String removeConsecutive(String str, char remove) {
    final StringBuilder sb = new StringBuilder(str.length());
    int i = 0;

    while(i < str.length()) {
        if(i == 0 || str.charAt(i) != remove || str.charAt(i) != str.charAt(i-1)) 
            sb.append(str.charAt(i));
        i++;
    }

    return sb.toString();
}
\$\endgroup\$
1
\$\begingroup\$

This is another solution:

public static String removeConsecutive(String str, char remove)
{
    final StringBuilder sb = new StringBuilder(str.length());
    boolean seen = false;

    for (final char c: str.toCharArray()) {
        if (c == remove) {
            if (!seen) {
                sb.append(c);
                seen = true;
            }
            continue;
        }
        seen = false;
        sb.append(c);
    }

    return sb.toString();
}
\$\endgroup\$
1
\$\begingroup\$

This may be not the most efficient solution but works fine

public static String removeConsecutive(String str, char remove) {
    String result = str;
    String removeAsString = String.valueOf(remove);
    String searchText =  removeAsString + removeAsString;

    while(result.indexOf(searchText) > -1) {
        result = result.replace(searchtext, removeAsString);
    }

    return result;
}
\$\endgroup\$
1
\$\begingroup\$

This one came from my friend, sticking to the original char array idea:

private static String removeConsecutive(final String str, final char remove) {
    final char[] chars = str.toCharArray();

    char current;
    char previous = 0;

    int i = 0, result = 0;
    while (i < chars.length) {
        current = chars[i];

        if (current != previous || current != remove) {
            chars[result++] = current;
        }

        previous = current;
        ++i;
    }

    return new String(chars, 0, result);
}
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.