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.
6 Answers 6
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();
}
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.
-
\$\begingroup\$
{1,}
is just+
;) \$\endgroup\$fge– fge2013年06月13日 09:35:30 +00:00Commented Jun 13, 2013 at 9:35 -
\$\begingroup\$ @fge changed, both works \$\endgroup\$cl-r– cl-r2013年06月13日 09:38:35 +00:00Commented 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– robosoul2013年06月13日 10:20:21 +00:00Commented 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– cl-r2013年06月13日 10:33:45 +00:00Commented Jun 13, 2013 at 10:33 -
\$\begingroup\$ Nit: When matching a single character
0+
does the same job as[0]+
. \$\endgroup\$l0b0– l0b02013年06月13日 12:23:05 +00:00Commented Jun 13, 2013 at 12:23
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();
}
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();
}
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;
}
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);
}