1

I have a string of comma-separated user-ids and I want to eliminate/remove specific user-id from a string.

I’ve following possibilities of string and expected the result

int elimiateUserId = 11;

String css1 = "11,22,33,44,55";
String css2 = "22,33,11,44,55";
String css3 = "22,33,44,55,11";
// The expected result in all cases, after replacement, should be:
// "22,33,44,55"

I tried the following:

String result = css#.replaceAll("," + elimiateUserId, "");  // # =  1 or 2 or 3
result = css#.replaceAll(elimiateUserId + "," , "");

This logic fails in case of css3. Please suggest me a proper solution for this issue.

Note: I'm working with Java 7

I checked around the following posts, but could not find any solution:

3
  • 1
    Split by comma, remove unwanted elements, join by comma. Commented Jun 29, 2017 at 14:15
  • @SebastianProske I'm developing this logic for web service response and there may be multiple request at a same time. These are sample strings, I've more than 1000 user-ids in string. I can't use split method as it may use loop iterations, which can be result into delay. Commented Jun 29, 2017 at 14:17
  • Try using the regex \b11\b. Commented Jun 29, 2017 at 14:26

10 Answers 10

7

You can use the Stream API in Java 8:

int elimiateUserId = 11;
String css1 = "11,22,33,44,55";

String css1Result = Stream.of(css1.split(","))
    .filter(value -> !String.valueOf(elimiateUserId).equals(value))
    .collect(Collectors.joining(","));

// css1Result = 22,33,44,55
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for your answer, but I'm working with Java 7. Please suggest me proper solution for Java 7. I'm working on server side logic so, can't change Java Platform
5

If you want to use regex, you may use (remember to properly escape as java string literal)

,\b11\b|\b11\b,

This will ensure that 11 won't be matched as part of another number due to the word boundaries and only one comma (if two are present) is matched and removed.

2 Comments

Short and sweet :) I eventually came to the same answer in my own over-wordy answer, since Java sadly won't accept regex conditionals.
Though thinking about it, the \bs between the commas and numbers are redundant, since it's always a word boundary.
5

You may build a regex like

^11,|,11\b

that will match 11, at the start of a string (^11,) or (|) ,11 not followed with any other word char (,11\b).

See the regex demo.

int elimiate_user_id = 11;
String pattern = "^" + elimiate_user_id + ",|," + elimiate_user_id + "\\b";
System.out.println("11,22,33,44,55,111".replaceAll(pattern, "")); // => 22,33,44,55,111
System.out.println("22,33,11,44,55,111".replaceAll(pattern, "")); // => 22,33,44,55,111 
System.out.println("22,33,44,55,111,11".replaceAll(pattern, "")); // => 22,33,44,55,111

See the Java demo

Comments

4

Try to (^(11)(?:,))|((?<=,)(11)(?:,))|(,11$) expression to replaceAll:

final String regexp = MessageFormat.format("(^({0})(?:,))|((?<=,)({0})(?:,))|(,{0}$)", elimiateUserId)
String result = css#.replaceAll(regexp, "") //for all cases.  

Here is an example: https://regex101.com/r/LwJgRu/3

4 Comments

This will remove an extra comma in the string 22,33,11,44,55,66.
It would also match 11 in ...,3114,....
Result for css2 = 22,3344,55,66
@svasa, really.. And one more issue that it can replace an id if it is a part of another one.
3

try this:

String result = css#.replaceAll("," + elimiateUserId, "")
             .replaceAll(elimiateUserId + "," , "");

1 Comment

What about "11,22,333,44".replaceAll(",33", "").replaceAll("33,", "")? The result would be "11,223,44" – clearly doesn't seem right.
3

You can use two replace in one shot like :

int elimiateUserId = 11;
String result = css#.replace("," + elimiateUserId , "").replace(elimiateUserId + ",", "");

If your string is like ,11 the the first replace will do replace it with empty
If your string is like 11, the the second replace will do replace it with empty

result

11,22,33,44,55      ->     22,33,44,55
22,33,11,44,55      ->     22,33,44,55
22,33,44,55,11      ->     22,33,44,55

ideone demo

1 Comment

What about "11,22,333,44".replaceAll(",33", "").replaceAll("33,", "")? The result would be "11,223,44" – clearly doesn't seem right.
3
String result = css#.replaceAll("," + eliminate_user_id + "\b|\b" + eliminate_user_id + ",", '');

The regular expression here is:

,     A leading comma.
eliminate_user_id  I assumed the missing 'n' here was a typo.
\b    Word boundary: word/number characters end here.
|     OR
\b    Word boundary: word/number characters begin here.
eliminate_user_id again.
,     A trailing comma.

The word boundary marker, matching the beginning or end of a "word", is the magic here. It means that the 11 will match in these strings:

11,22,33,44,55
22,33,11,44,55
22,33,44,55,11 

But not these strings:

111,112,113,114
411,311,211,111

There's a cleaner way, though:

String result = css#.replaceAll("(,?)\b" + eliminate_user_id + "\b(?(1)|,)", "");

The regular expression here is:

(     A capturing group - what's in here, is in group 1.
,?    An optional leading comma.
)     End the capturing group.
\b    Word boundary: word/number characters begin here.
eliminate_user_id  I assumed the missing 'n' here was a typo.
\b    Word boundary: word/number characters end here.
(?(1) If there's something in group 1, then require...
|     ...nothing, but if there was nothing, then require...
,     A trailing comma.
)     end the if.

The "if" part here is a little unusual - you can find a little more information on regex conditionals here: http://www.regular-expressions.info/conditional.html

I am not sure if Java supports regex conditionals. Some posts here (Conditional Regular Expression in Java?) suggest that it does not :(


Side-note: for performance, if the list is VERY long and there are VERY many removals to be performed, the most obvious option is to just run the above line for each number to be removed:

String css = "11,22,33,44,55,66,77,88,99,1010,1111,1212,...";
Array<String> removals = ["11", "33", "55", "77", "99", "1212"];
for (i=0; i<removals.length; i++) {
  css = css.replaceAll("," + removals[i] + "\b|\b" + eliminate_user_id + ",", "");
}

(code not tested: don't have access to a Java compiler here)

This will be fast enough (worst case scales with about O(m*n) for m removals from a string of n ids), but we can maybe do better.

One is to build the regex to be \b(11,42,18,13,123,...etc)\b - that is, make the regex search for all ids to be removed at the same time. In theory this scales a little worse, scaling with O(m*n) in every case rather than jut the worst case, but in practice should be considerably faster.

String css = "11,22,33,44,55,66,77,88,99,1010,1111,1212,...";
Array<String> removals = ["11", "33", "55", "77", "99", "1212"];
String removalsStr = String.join("|", removals);
css = css.replaceAll("," + removalsStr + "\b|\b" + removalsStr + ",", "");

But another approach might be to build a hashtable of the ids in the long string, then remove all the ids from the hashtable, then concatenate the remaining hashtable keys back into a string. Since hashtable lookups are effectively O(1) for sparse hashtables, that makes this scale with O(n). The tradeoff here is the extra memory for that hashtable, though.

(I don't think I can do this version without a java compiler handy. I would not recommend this approach unless you have a VAST (many thousands) list of IDs to remove, anyway, as it will be much uglier and more complex code).

7 Comments

This may not work in case of 22,33,44,55,11 Please look at this link and correct me, if I'm wrong (regex101.com/r/75Bg0K/1).
@Krunal I see all "11"s highlighted in that link, and marked as "full match". Do you not?
Yes, but result of css3 is 22,33,44,55,66, There is an extra comma, at the end of string
Good call. ,\b11\b|\b11\b,? works, but I'm trying to figure out a nicer way to do it, preferably without repeating the eliminate_user_id variable... tricky.
Thank for your time and such nice answer but previous one logic, left a single comma at last, can you please provide an exact solution with your previous logic :)
|
1

I think its safer to maintain a whitelist and then use it as a reference to make further changes.

List<String> whitelist = Arrays.asList("22", "33", "44", "55");
String s = "22,33,44,55,11";
String[] sArr = s.split(",");
StringBuilder ids = new StringBuilder();
for (String id : sArr) {
    if (whitelist.contains(id)) {
        ids.append(id).append(", ");
    }
}
String r = ids.substring(0, ids.length() - 2);
System.out.println(r);

2 Comments

thank for your answer, but I can't use loop iteration.. I'm developing this logic for web service response and there may be multiple request at a same time. These are sample strings, I've more than 1000 user-ids in string. I can't use split method as it may use loop iterations, which can be result into delay.
Ok. Thanks for the info @Krunal. My thinking is that anyway the multiple requests are probably going to use separate threads for execution. And when it comes to whitelisting user-ids its better to err on the side of safety. Also, replaceAll also uses iteration internally as its a O(n) function. But again you know your system better.
0

If you need a solution with Regex, then the following works perfectly.

    int elimiate_user_id = 11;

    String css1 = "11,22,33,44,55";
    String css2 = "22,33,11,44,55";   
    String css3 = "22,33,44,55,11";

    String resultCss=css1.replaceAll(elimiate_user_id+"[,]*", "").replaceAll(",$", "");

I works with all types of input you desire.

2 Comments

Why two regexes (the second seems redundant), and why [,]* instead of ,?? This will also, like most other solutions, break with longer numbers like 2112.
@DewiMorgan, yeah ? would do as well. And the second replaceAll is not redundant.. its to make sure we remove the trailing commas(if any)
-2

This should work

replaceAll("(11,|,11)", "")

At least when you can guarantee when there is no 311, or ,113 or so

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.